ar-key.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /* RxRPC key management
  2. *
  3. * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. *
  11. * RxRPC keys should have a description of describing their purpose:
  12. * "afs@CAMBRIDGE.REDHAT.COM>
  13. */
  14. #include <linux/module.h>
  15. #include <linux/net.h>
  16. #include <linux/skbuff.h>
  17. #include <linux/key-type.h>
  18. #include <linux/crypto.h>
  19. #include <linux/ctype.h>
  20. #include <net/sock.h>
  21. #include <net/af_rxrpc.h>
  22. #include <keys/rxrpc-type.h>
  23. #include <keys/user-type.h>
  24. #include "ar-internal.h"
  25. static int rxrpc_instantiate(struct key *, const void *, size_t);
  26. static int rxrpc_instantiate_s(struct key *, const void *, size_t);
  27. static void rxrpc_destroy(struct key *);
  28. static void rxrpc_destroy_s(struct key *);
  29. static void rxrpc_describe(const struct key *, struct seq_file *);
  30. /*
  31. * rxrpc defined keys take an arbitrary string as the description and an
  32. * arbitrary blob of data as the payload
  33. */
  34. struct key_type key_type_rxrpc = {
  35. .name = "rxrpc",
  36. .instantiate = rxrpc_instantiate,
  37. .match = user_match,
  38. .destroy = rxrpc_destroy,
  39. .describe = rxrpc_describe,
  40. };
  41. EXPORT_SYMBOL(key_type_rxrpc);
  42. /*
  43. * rxrpc server defined keys take "<serviceId>:<securityIndex>" as the
  44. * description and an 8-byte decryption key as the payload
  45. */
  46. struct key_type key_type_rxrpc_s = {
  47. .name = "rxrpc_s",
  48. .instantiate = rxrpc_instantiate_s,
  49. .match = user_match,
  50. .destroy = rxrpc_destroy_s,
  51. .describe = rxrpc_describe,
  52. };
  53. /*
  54. * parse an RxKAD type XDR format token
  55. * - the caller guarantees we have at least 4 words
  56. */
  57. static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
  58. unsigned toklen)
  59. {
  60. struct rxrpc_key_token *token;
  61. size_t plen;
  62. u32 tktlen;
  63. int ret;
  64. _enter(",{%x,%x,%x,%x},%u",
  65. ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
  66. toklen);
  67. if (toklen <= 8 * 4)
  68. return -EKEYREJECTED;
  69. tktlen = ntohl(xdr[7]);
  70. _debug("tktlen: %x", tktlen);
  71. if (tktlen > AFSTOKEN_RK_TIX_MAX)
  72. return -EKEYREJECTED;
  73. if (8 * 4 + tktlen != toklen)
  74. return -EKEYREJECTED;
  75. plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
  76. ret = key_payload_reserve(key, key->datalen + plen);
  77. if (ret < 0)
  78. return ret;
  79. plen -= sizeof(*token);
  80. token = kmalloc(sizeof(*token), GFP_KERNEL);
  81. if (!token)
  82. return -ENOMEM;
  83. token->kad = kmalloc(plen, GFP_KERNEL);
  84. if (!token->kad) {
  85. kfree(token);
  86. return -ENOMEM;
  87. }
  88. token->security_index = RXRPC_SECURITY_RXKAD;
  89. token->kad->ticket_len = tktlen;
  90. token->kad->vice_id = ntohl(xdr[0]);
  91. token->kad->kvno = ntohl(xdr[1]);
  92. token->kad->start = ntohl(xdr[4]);
  93. token->kad->expiry = ntohl(xdr[5]);
  94. token->kad->primary_flag = ntohl(xdr[6]);
  95. memcpy(&token->kad->session_key, &xdr[2], 8);
  96. memcpy(&token->kad->ticket, &xdr[8], tktlen);
  97. _debug("SCIX: %u", token->security_index);
  98. _debug("TLEN: %u", token->kad->ticket_len);
  99. _debug("EXPY: %x", token->kad->expiry);
  100. _debug("KVNO: %u", token->kad->kvno);
  101. _debug("PRIM: %u", token->kad->primary_flag);
  102. _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
  103. token->kad->session_key[0], token->kad->session_key[1],
  104. token->kad->session_key[2], token->kad->session_key[3],
  105. token->kad->session_key[4], token->kad->session_key[5],
  106. token->kad->session_key[6], token->kad->session_key[7]);
  107. if (token->kad->ticket_len >= 8)
  108. _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
  109. token->kad->ticket[0], token->kad->ticket[1],
  110. token->kad->ticket[2], token->kad->ticket[3],
  111. token->kad->ticket[4], token->kad->ticket[5],
  112. token->kad->ticket[6], token->kad->ticket[7]);
  113. /* count the number of tokens attached */
  114. key->type_data.x[0]++;
  115. /* attach the data */
  116. token->next = key->payload.data;
  117. key->payload.data = token;
  118. if (token->kad->expiry < key->expiry)
  119. key->expiry = token->kad->expiry;
  120. _leave(" = 0");
  121. return 0;
  122. }
  123. /*
  124. * attempt to parse the data as the XDR format
  125. * - the caller guarantees we have more than 7 words
  126. */
  127. static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datalen)
  128. {
  129. const __be32 *xdr = data, *token;
  130. const char *cp;
  131. unsigned len, tmp, loop, ntoken, toklen, sec_ix;
  132. int ret;
  133. _enter(",{%x,%x,%x,%x},%zu",
  134. ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
  135. datalen);
  136. if (datalen > AFSTOKEN_LENGTH_MAX)
  137. goto not_xdr;
  138. /* XDR is an array of __be32's */
  139. if (datalen & 3)
  140. goto not_xdr;
  141. /* the flags should be 0 (the setpag bit must be handled by
  142. * userspace) */
  143. if (ntohl(*xdr++) != 0)
  144. goto not_xdr;
  145. datalen -= 4;
  146. /* check the cell name */
  147. len = ntohl(*xdr++);
  148. if (len < 1 || len > AFSTOKEN_CELL_MAX)
  149. goto not_xdr;
  150. datalen -= 4;
  151. tmp = (len + 3) & ~3;
  152. if (tmp > datalen)
  153. goto not_xdr;
  154. cp = (const char *) xdr;
  155. for (loop = 0; loop < len; loop++)
  156. if (!isprint(cp[loop]))
  157. goto not_xdr;
  158. if (len < tmp)
  159. for (; loop < tmp; loop++)
  160. if (cp[loop])
  161. goto not_xdr;
  162. _debug("cellname: [%u/%u] '%*.*s'",
  163. len, tmp, len, len, (const char *) xdr);
  164. datalen -= tmp;
  165. xdr += tmp >> 2;
  166. /* get the token count */
  167. if (datalen < 12)
  168. goto not_xdr;
  169. ntoken = ntohl(*xdr++);
  170. datalen -= 4;
  171. _debug("ntoken: %x", ntoken);
  172. if (ntoken < 1 || ntoken > AFSTOKEN_MAX)
  173. goto not_xdr;
  174. /* check each token wrapper */
  175. token = xdr;
  176. loop = ntoken;
  177. do {
  178. if (datalen < 8)
  179. goto not_xdr;
  180. toklen = ntohl(*xdr++);
  181. sec_ix = ntohl(*xdr);
  182. datalen -= 4;
  183. _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
  184. if (toklen < 20 || toklen > datalen)
  185. goto not_xdr;
  186. datalen -= (toklen + 3) & ~3;
  187. xdr += (toklen + 3) >> 2;
  188. } while (--loop > 0);
  189. _debug("remainder: %zu", datalen);
  190. if (datalen != 0)
  191. goto not_xdr;
  192. /* okay: we're going to assume it's valid XDR format
  193. * - we ignore the cellname, relying on the key to be correctly named
  194. */
  195. do {
  196. xdr = token;
  197. toklen = ntohl(*xdr++);
  198. token = xdr + ((toklen + 3) >> 2);
  199. sec_ix = ntohl(*xdr++);
  200. toklen -= 4;
  201. switch (sec_ix) {
  202. case RXRPC_SECURITY_RXKAD:
  203. ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen);
  204. if (ret != 0)
  205. goto error;
  206. break;
  207. default:
  208. ret = -EPROTONOSUPPORT;
  209. goto error;
  210. }
  211. } while (--ntoken > 0);
  212. _leave(" = 0");
  213. return 0;
  214. not_xdr:
  215. _leave(" = -EPROTO");
  216. return -EPROTO;
  217. error:
  218. _leave(" = %d", ret);
  219. return ret;
  220. }
  221. /*
  222. * instantiate an rxrpc defined key
  223. * data should be of the form:
  224. * OFFSET LEN CONTENT
  225. * 0 4 key interface version number
  226. * 4 2 security index (type)
  227. * 6 2 ticket length
  228. * 8 4 key expiry time (time_t)
  229. * 12 4 kvno
  230. * 16 8 session key
  231. * 24 [len] ticket
  232. *
  233. * if no data is provided, then a no-security key is made
  234. */
  235. static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen)
  236. {
  237. const struct rxrpc_key_data_v1 *v1;
  238. struct rxrpc_key_token *token, **pp;
  239. size_t plen;
  240. u32 kver;
  241. int ret;
  242. _enter("{%x},,%zu", key_serial(key), datalen);
  243. /* handle a no-security key */
  244. if (!data && datalen == 0)
  245. return 0;
  246. /* determine if the XDR payload format is being used */
  247. if (datalen > 7 * 4) {
  248. ret = rxrpc_instantiate_xdr(key, data, datalen);
  249. if (ret != -EPROTO)
  250. return ret;
  251. }
  252. /* get the key interface version number */
  253. ret = -EINVAL;
  254. if (datalen <= 4 || !data)
  255. goto error;
  256. memcpy(&kver, data, sizeof(kver));
  257. data += sizeof(kver);
  258. datalen -= sizeof(kver);
  259. _debug("KEY I/F VERSION: %u", kver);
  260. ret = -EKEYREJECTED;
  261. if (kver != 1)
  262. goto error;
  263. /* deal with a version 1 key */
  264. ret = -EINVAL;
  265. if (datalen < sizeof(*v1))
  266. goto error;
  267. v1 = data;
  268. if (datalen != sizeof(*v1) + v1->ticket_length)
  269. goto error;
  270. _debug("SCIX: %u", v1->security_index);
  271. _debug("TLEN: %u", v1->ticket_length);
  272. _debug("EXPY: %x", v1->expiry);
  273. _debug("KVNO: %u", v1->kvno);
  274. _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
  275. v1->session_key[0], v1->session_key[1],
  276. v1->session_key[2], v1->session_key[3],
  277. v1->session_key[4], v1->session_key[5],
  278. v1->session_key[6], v1->session_key[7]);
  279. if (v1->ticket_length >= 8)
  280. _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
  281. v1->ticket[0], v1->ticket[1],
  282. v1->ticket[2], v1->ticket[3],
  283. v1->ticket[4], v1->ticket[5],
  284. v1->ticket[6], v1->ticket[7]);
  285. ret = -EPROTONOSUPPORT;
  286. if (v1->security_index != RXRPC_SECURITY_RXKAD)
  287. goto error;
  288. plen = sizeof(*token->kad) + v1->ticket_length;
  289. ret = key_payload_reserve(key, plen + sizeof(*token));
  290. if (ret < 0)
  291. goto error;
  292. ret = -ENOMEM;
  293. token = kmalloc(sizeof(*token), GFP_KERNEL);
  294. if (!token)
  295. goto error;
  296. token->kad = kmalloc(plen, GFP_KERNEL);
  297. if (!token->kad)
  298. goto error_free;
  299. token->security_index = RXRPC_SECURITY_RXKAD;
  300. token->kad->ticket_len = v1->ticket_length;
  301. token->kad->expiry = v1->expiry;
  302. token->kad->kvno = v1->kvno;
  303. memcpy(&token->kad->session_key, &v1->session_key, 8);
  304. memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
  305. /* attach the data */
  306. key->type_data.x[0]++;
  307. pp = (struct rxrpc_key_token **)&key->payload.data;
  308. while (*pp)
  309. pp = &(*pp)->next;
  310. *pp = token;
  311. if (token->kad->expiry < key->expiry)
  312. key->expiry = token->kad->expiry;
  313. token = NULL;
  314. ret = 0;
  315. error_free:
  316. kfree(token);
  317. error:
  318. return ret;
  319. }
  320. /*
  321. * instantiate a server secret key
  322. * data should be a pointer to the 8-byte secret key
  323. */
  324. static int rxrpc_instantiate_s(struct key *key, const void *data,
  325. size_t datalen)
  326. {
  327. struct crypto_blkcipher *ci;
  328. _enter("{%x},,%zu", key_serial(key), datalen);
  329. if (datalen != 8)
  330. return -EINVAL;
  331. memcpy(&key->type_data, data, 8);
  332. ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
  333. if (IS_ERR(ci)) {
  334. _leave(" = %ld", PTR_ERR(ci));
  335. return PTR_ERR(ci);
  336. }
  337. if (crypto_blkcipher_setkey(ci, data, 8) < 0)
  338. BUG();
  339. key->payload.data = ci;
  340. _leave(" = 0");
  341. return 0;
  342. }
  343. /*
  344. * dispose of the data dangling from the corpse of a rxrpc key
  345. */
  346. static void rxrpc_destroy(struct key *key)
  347. {
  348. struct rxrpc_key_token *token;
  349. while ((token = key->payload.data)) {
  350. key->payload.data = token->next;
  351. switch (token->security_index) {
  352. case RXRPC_SECURITY_RXKAD:
  353. kfree(token->kad);
  354. break;
  355. default:
  356. printk(KERN_ERR "Unknown token type %x on rxrpc key\n",
  357. token->security_index);
  358. BUG();
  359. }
  360. kfree(token);
  361. }
  362. }
  363. /*
  364. * dispose of the data dangling from the corpse of a rxrpc key
  365. */
  366. static void rxrpc_destroy_s(struct key *key)
  367. {
  368. if (key->payload.data) {
  369. crypto_free_blkcipher(key->payload.data);
  370. key->payload.data = NULL;
  371. }
  372. }
  373. /*
  374. * describe the rxrpc key
  375. */
  376. static void rxrpc_describe(const struct key *key, struct seq_file *m)
  377. {
  378. seq_puts(m, key->description);
  379. }
  380. /*
  381. * grab the security key for a socket
  382. */
  383. int rxrpc_request_key(struct rxrpc_sock *rx, char __user *optval, int optlen)
  384. {
  385. struct key *key;
  386. char *description;
  387. _enter("");
  388. if (optlen <= 0 || optlen > PAGE_SIZE - 1)
  389. return -EINVAL;
  390. description = kmalloc(optlen + 1, GFP_KERNEL);
  391. if (!description)
  392. return -ENOMEM;
  393. if (copy_from_user(description, optval, optlen)) {
  394. kfree(description);
  395. return -EFAULT;
  396. }
  397. description[optlen] = 0;
  398. key = request_key(&key_type_rxrpc, description, NULL);
  399. if (IS_ERR(key)) {
  400. kfree(description);
  401. _leave(" = %ld", PTR_ERR(key));
  402. return PTR_ERR(key);
  403. }
  404. rx->key = key;
  405. kfree(description);
  406. _leave(" = 0 [key %x]", key->serial);
  407. return 0;
  408. }
  409. /*
  410. * grab the security keyring for a server socket
  411. */
  412. int rxrpc_server_keyring(struct rxrpc_sock *rx, char __user *optval,
  413. int optlen)
  414. {
  415. struct key *key;
  416. char *description;
  417. _enter("");
  418. if (optlen <= 0 || optlen > PAGE_SIZE - 1)
  419. return -EINVAL;
  420. description = kmalloc(optlen + 1, GFP_KERNEL);
  421. if (!description)
  422. return -ENOMEM;
  423. if (copy_from_user(description, optval, optlen)) {
  424. kfree(description);
  425. return -EFAULT;
  426. }
  427. description[optlen] = 0;
  428. key = request_key(&key_type_keyring, description, NULL);
  429. if (IS_ERR(key)) {
  430. kfree(description);
  431. _leave(" = %ld", PTR_ERR(key));
  432. return PTR_ERR(key);
  433. }
  434. rx->securities = key;
  435. kfree(description);
  436. _leave(" = 0 [key %x]", key->serial);
  437. return 0;
  438. }
  439. /*
  440. * generate a server data key
  441. */
  442. int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
  443. const void *session_key,
  444. time_t expiry,
  445. u32 kvno)
  446. {
  447. const struct cred *cred = current_cred();
  448. struct key *key;
  449. int ret;
  450. struct {
  451. u32 kver;
  452. struct rxrpc_key_data_v1 v1;
  453. } data;
  454. _enter("");
  455. key = key_alloc(&key_type_rxrpc, "x", 0, 0, cred, 0,
  456. KEY_ALLOC_NOT_IN_QUOTA);
  457. if (IS_ERR(key)) {
  458. _leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
  459. return -ENOMEM;
  460. }
  461. _debug("key %d", key_serial(key));
  462. data.kver = 1;
  463. data.v1.security_index = RXRPC_SECURITY_RXKAD;
  464. data.v1.ticket_length = 0;
  465. data.v1.expiry = expiry;
  466. data.v1.kvno = 0;
  467. memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
  468. ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
  469. if (ret < 0)
  470. goto error;
  471. conn->key = key;
  472. _leave(" = 0 [%d]", key_serial(key));
  473. return 0;
  474. error:
  475. key_revoke(key);
  476. key_put(key);
  477. _leave(" = -ENOMEM [ins %d]", ret);
  478. return -ENOMEM;
  479. }
  480. EXPORT_SYMBOL(rxrpc_get_server_data_key);
  481. /**
  482. * rxrpc_get_null_key - Generate a null RxRPC key
  483. * @keyname: The name to give the key.
  484. *
  485. * Generate a null RxRPC key that can be used to indicate anonymous security is
  486. * required for a particular domain.
  487. */
  488. struct key *rxrpc_get_null_key(const char *keyname)
  489. {
  490. const struct cred *cred = current_cred();
  491. struct key *key;
  492. int ret;
  493. key = key_alloc(&key_type_rxrpc, keyname, 0, 0, cred,
  494. KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA);
  495. if (IS_ERR(key))
  496. return key;
  497. ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL);
  498. if (ret < 0) {
  499. key_revoke(key);
  500. key_put(key);
  501. return ERR_PTR(ret);
  502. }
  503. return key;
  504. }
  505. EXPORT_SYMBOL(rxrpc_get_null_key);