1 /* rxgk/rxgk_crypto_rfc3961.c - Wrappers for RFC3961 crypto used in RXGK. */
3 * Copyright (C) 2013, 2014 by the Massachusetts Institute of Technology.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Wrappers for the RFC3961 crypto routines used by RXGK, and
35 * helpers. This implementation uses the in-tree rfc3961 library, but
36 * we do not expose those types in our interface so as to be
37 * compatible with other backends in the future. It should be possible
38 * to backend to an out-of-tree krb5 library or the kernel's crypto
39 * framework using this API.
41 * Public functions in this file should return RXGK error codes, because
42 * error codes from these functions can end up on the wire. This will
43 * entail converting from any krb5 error codes that are used internally.
46 #include <afsconfig.h>
47 #include <afs/param.h>
51 # include "afs/sysincludes.h"
52 # include "afsincludes.h"
59 #include <afs/rfc3961.h>
62 #include "rxgk_private.h"
65 * This is what an rxgk_key really is, but it's a 'struct rxgk_key_s' to consumers:
66 * typedef struct rxgk_keyblock * rxgk_key;
68 struct rxgk_keyblock {
69 /* A krb5 context for this key, only to be used for initialization and
70 * destruction of the key. Do not use this for actually using the key for
71 * crypto operations; we are supposed to avoid accessing it in multiple
72 * threads at the same time. */
73 krb5_context init_ctx;
78 struct rxgk_keyblock keyblock;
81 /* Convenience macro; reduces the diff if an MIT krb5 backend is made. */
82 #define deref_keyblock_enctype(k) krb5_keyblock_get_enctype(k)
84 /* Convenience functions to convert between the opaque rxgk_key type and our
85 * internal rxgk_keyblock struct. */
86 static_inline struct rxgk_keyblock *
87 key2keyblock(rxgk_key key)
89 return &key->keyblock;
92 static_inline rxgk_key
93 keyblock2key(struct rxgk_keyblock *keyblock)
95 return (rxgk_key)keyblock;
99 * Convert krb5 error code to RXGK error code. Don't let the krb5 codes escape.
101 static_inline afs_int32
105 if (err >= ERROR_TABLE_BASE_RXGK && err < (ERROR_TABLE_BASE_RXGK + 256))
111 return RXGK_INCONSISTENCY;
116 * Convert a krb5 enctype to a krb5 checksum type.
118 * Each enctype has a mandatory (to implement) checksum type, which can be
119 * chosen when computing a checksum by passing 0 for the type parameter.
120 * However, we must separately compute the length of a checksum on a message in
121 * order to extract the checksum from a packet at RXGK_LEVEL_AUTH, and Heimdal
122 * krb5 does not expose a way to get the mandatory checksum type for a given
123 * enctype. So, we get to do it ourselves.
125 * @return -1 on failure, otherwise the checksum type.
127 static_inline afs_int32
128 etoc(afs_int32 etype)
131 case ETYPE_DES_CBC_CRC:
132 return CKSUMTYPE_RSA_MD5_DES;
133 case ETYPE_DES_CBC_MD4:
134 return CKSUMTYPE_RSA_MD4_DES;
135 case ETYPE_DES_CBC_MD5:
136 return CKSUMTYPE_RSA_MD5_DES;
137 case ETYPE_DES3_CBC_SHA1:
138 return CKSUMTYPE_HMAC_SHA1_DES3;
139 case ETYPE_ARCFOUR_MD4:
140 return CKSUMTYPE_HMAC_MD5_ENC;
141 case ETYPE_AES128_CTS_HMAC_SHA1_96:
142 return CKSUMTYPE_HMAC_SHA1_96_AES_128;
143 case ETYPE_AES256_CTS_HMAC_SHA1_96:
144 return CKSUMTYPE_HMAC_SHA1_96_AES_256;
151 * Get the number of octets of input needed for a key of the given etype,
153 * @return -1 on error, or the number of octets of input needed on success.
156 rxgk_etype_to_len(int etype)
159 krb5_error_code code;
162 code = krb5_init_context(&ctx);
165 code = krb5_enctype_keybits(ctx, etype, &bits);
166 krb5_free_context(ctx);
169 return (bits + 7) / 8;
173 * Take a raw key from some external source and produce an rxgk_key from it.
175 * The raw_key and length are not an RXGK_Data because in some cases they will
176 * come from a gss_buffer and there's no real need to do the conversion.
177 * The caller must use rxgk_release_key to deallocate memory allocated for the
180 * This routine checks whether the length of the supplied key data matches the
181 * key generation seed length for the requested enctype, in which case the RFC
182 * 3961 random_to_key operation is performed, or if it is the actual (output)
183 * key length, in which case the key data is used as-is.
185 * @param key_out the returned rxgk_key.
186 * @param raw_key a pointer to the octet stream of the key input data.
187 * @param length the length of raw_key (in octets).
188 * @param enctype the RFC 3961 enctype of the key being constructed.
189 * @return rxgk error codes.
192 rxgk_make_key(rxgk_key *key_out, void *raw_key, afs_uint32 length,
195 struct rxgk_keyblock *new_key = NULL;
198 ssize_t input_length;
200 /* Must initialize before we return. */
203 new_key = rxi_Alloc(sizeof(*new_key));
204 if (new_key == NULL) {
205 ret = RXGK_INCONSISTENCY;
208 ret = krb5_init_context(&new_key->init_ctx);
211 ret = krb5_enctype_keysize(new_key->init_ctx, enctype, &full_length);
214 input_length = rxgk_etype_to_len(enctype);
215 if (input_length < 0) {
216 ret = RXGK_INCONSISTENCY;
219 if (length == full_length) {
220 /* free with krb5_free_keyblock_contents + rxi_Free */
221 ret = krb5_keyblock_init(new_key->init_ctx, enctype, raw_key, length,
223 } else if (length == input_length) {
224 /* free with krb5_free_keyblock_contents + rxi_Free */
225 ret = krb5_random_to_key(new_key->init_ctx, enctype, raw_key, length,
232 *key_out = keyblock2key(new_key);
234 if (ret != 0 && new_key != NULL) {
235 if (new_key->init_ctx != NULL) {
236 krb5_free_context(new_key->init_ctx);
238 rxi_Free(new_key, sizeof(*new_key));
246 * The caller must use rxgk_release_key to deallocate the memory allocated
247 * for the new rxgk_key.
249 * @param[in] key_in The key to be copied.
250 * @param[out] key_out A copy of key_in.
251 * @return rxgk error codes.
254 rxgk_copy_key(rxgk_key key_in, rxgk_key *key_out)
256 struct rxgk_keyblock *keyblock;
258 keyblock = key2keyblock(key_in);
259 return rxgk_make_key(key_out, keyblock->key.keyvalue.data,
260 keyblock->key.keyvalue.length, keyblock->key.keytype);
264 * Generate a random key.
266 * The caller must use rxgk_release_key to deallocate the memory allocated
267 * for the new rxgk_key.
269 * @param[inout] enctype The RFC 3961 enctype of the key to be generated. If
270 * 0, set this to a default enctype, and use that
271 * enctype for the generated key.
272 * @param[out] key_out The random rxgk key.
273 * @return rxgk error codes.
276 rxgk_random_key(afs_int32 *enctype, rxgk_key *key_out)
286 *enctype = ETYPE_AES128_CTS_HMAC_SHA1_96;
288 len = rxgk_etype_to_len(*enctype);
290 return RXGK_INCONSISTENCY;
291 buf = rxi_Alloc(len);
293 return RXGK_INCONSISTENCY;
294 krb5_generate_random_block(buf, (size_t)len);
295 ret = rxgk_make_key(key_out, buf, len, *enctype);
301 * Release the storage underlying an rxgk key
303 * Call into the underlying library to release any storage allocated for
304 * the rxgk_key, and null out the key pointer.
307 rxgk_release_key(rxgk_key *key)
309 struct rxgk_keyblock *keyblock;
313 keyblock = key2keyblock(*key);
315 krb5_free_keyblock_contents(keyblock->init_ctx, &keyblock->key);
316 if (keyblock->init_ctx != NULL) {
317 krb5_free_context(keyblock->init_ctx);
319 rxi_Free(keyblock, sizeof(*keyblock));
324 * Determine the length of a checksum (MIC) using the specified key.
326 * @param[in] key The rxgk_key being queried.
327 * @param[out] out The length of a checksum made using key.
328 * @return rxgk error codes.
331 rxgk_mic_length(rxgk_key key, size_t *out)
333 krb5_context ctx = NULL;
334 krb5_cksumtype cstype;
335 krb5_enctype enctype;
337 struct rxgk_keyblock *keyblock = key2keyblock(key);
342 ret = krb5_init_context(&ctx);
346 enctype = deref_keyblock_enctype(&keyblock->key);
347 cstype = etoc(enctype);
352 ret = krb5_checksumsize(ctx, cstype, &len);
359 krb5_free_context(ctx);
365 * Obtain the RFC 3961 Message Integrity Check of a buffer
367 * Call into the RFC 3961 encryption framework to obtain a Message Integrity
368 * Check of a buffer using the specified key and key usage. It is assumed
369 * that the rxgk_key structure includes the enctype information needed to
370 * determine which crypto routine to call.
372 * The output buffer is allocated with rx_opaque_populate() and must be freed
373 * by the caller (with rx_opaque_freeContents()).
375 * @param[in] key The key used to key the MIC.
376 * @param[in] usage The key usage value to use (from rxgk_int.h).
377 * @param[in] in The input buffer to be MICd.
378 * @param[out] out The MIC.
379 * @return rxgk error codes.
382 rxgk_mic_in_key(rxgk_key key, afs_int32 usage, RXGK_Data *in,
385 krb5_context ctx = NULL;
387 krb5_cksumtype cstype;
388 krb5_crypto crypto = NULL;
389 krb5_enctype enctype;
391 struct rxgk_keyblock *keyblock = key2keyblock(key);
394 memset(&cksum, 0, sizeof(cksum));
395 memset(out, 0, sizeof(*out));
397 ret = krb5_init_context(&ctx);
401 enctype = deref_keyblock_enctype(&keyblock->key);
402 cstype = etoc(enctype);
407 ret = krb5_checksumsize(ctx, cstype, &len);
410 ret = krb5_crypto_init(ctx, &keyblock->key, enctype, &crypto);
413 ret = krb5_create_checksum(ctx, crypto, usage, cstype, in->val,
418 if (len != cksum.checksum.length) {
419 ret = RXGK_INCONSISTENCY;
422 ret = rx_opaque_populate(out, cksum.checksum.data, len);
425 free_Checksum(&cksum);
427 krb5_crypto_destroy(ctx, crypto);
429 krb5_free_context(ctx);
435 * Verify the RFC 3961 Message Integrity Check on a message
437 * Call into the RFC 3961 encryption framework to verify a message integrity
438 * check on a message, using the specified key with the specified key usage.
439 * It is assumed that the rxgk_key structure includes the enctype information
440 * needed to determine which particular crypto routine to call.
442 * @param[in] key The key keying the checksum.
443 * @param[in] usage The key usage for the checksum.
444 * @param[in] in The buffer which was checksummed.
445 * @param[in] mic The MIC to be verified.
446 * @return rxgk error codes.
449 rxgk_check_mic_in_key(rxgk_key key, afs_int32 usage, RXGK_Data *in,
452 krb5_context ctx = NULL;
454 krb5_crypto crypto = NULL;
455 krb5_enctype enctype;
457 struct rxgk_keyblock *keyblock = key2keyblock(key);
459 memset(&cksum, 0, sizeof(cksum));
461 ret = krb5_init_context(&ctx);
465 enctype = deref_keyblock_enctype(&keyblock->key);
466 cksum.cksumtype = etoc(enctype);
467 ret = krb5_crypto_init(ctx, &keyblock->key, enctype, &crypto);
470 cksum.checksum.data = mic->val;
471 cksum.checksum.length = mic->len;
472 ret = krb5_verify_checksum(ctx, crypto, usage, in->val, in->len,
474 /* Un-alias the storage to avoid a double-free. */
475 cksum.checksum.data = NULL;
476 cksum.checksum.length = 0;
478 ret = RXGK_SEALED_INCON;
482 free_Checksum(&cksum);
484 krb5_crypto_destroy(ctx, crypto);
486 krb5_free_context(ctx);
492 * Encrypt a buffer in a key using the RFC 3961 framework
494 * Call into the RFC 3961 encryption framework to encrypt a buffer with
495 * specified key and key usage. It is assumed that the rxgk_key structure
496 * includes the enctype information needed to determine which particular
497 * crypto routine to call.
499 * The output buffer is allocated with rx_opaque_populate() and must be freed
500 * by the caller (with rx_opaque_freeContents()).
502 * @param[in] key The key used to encrypt the message.
503 * @param[in] usage The key usage for the encryption.
504 * @param[in] in The buffer being encrypted.
505 * @param[out] out The encrypted form of the message.
506 * @return rxgk error codes.
509 rxgk_encrypt_in_key(rxgk_key key, afs_int32 usage, RXGK_Data *in,
512 krb5_context ctx = NULL;
513 krb5_crypto crypto = NULL;
515 krb5_enctype enctype;
517 struct rxgk_keyblock *keyblock = key2keyblock(key);
519 memset(&kd_out, 0, sizeof(kd_out));
520 memset(out, 0, sizeof(*out));
522 ret = krb5_init_context(&ctx);
526 enctype = deref_keyblock_enctype(&keyblock->key);
527 ret = krb5_crypto_init(ctx, &keyblock->key, enctype, &crypto);
530 ret = krb5_encrypt(ctx, crypto, usage, in->val, in->len, &kd_out);
533 ret = rx_opaque_populate(out, kd_out.data, kd_out.length);
537 krb5_crypto_destroy(ctx, crypto);
538 krb5_data_free(&kd_out);
540 krb5_free_context(ctx);
546 * Decrypt a buffer using a given key in the RFC 3961 framework
548 * Call into the RFC 3961 encryption framework to decrypt a buffer with the
549 * specified key with the specified key usage. It is assumed that the
550 * rxgk_key structure includes the enctype information needed to determine
551 * which particular crypto routine to call.
553 * The output buffer is allocated with rx_opaque_populate() and must be freed
554 * by the caller (with rx_opaque_freeContents()).
556 * @param[in] key The key to use for the decryption.
557 * @param[in] usage The key usage used for the encryption.
558 * @param[in] in The encrypted message.
559 * @param[out] out The decrypted message.
560 * @return rxgk error codes.
563 rxgk_decrypt_in_key(rxgk_key key, afs_int32 usage, RXGK_Data *in,
566 krb5_context ctx = NULL;
567 krb5_crypto crypto = NULL;
569 krb5_enctype enctype;
571 struct rxgk_keyblock *keyblock = key2keyblock(key);
573 memset(out, 0, sizeof(*out));
574 memset(&kd_out, 0, sizeof(kd_out));
576 ret = krb5_init_context(&ctx);
580 enctype = deref_keyblock_enctype(&keyblock->key);
581 ret = krb5_crypto_init(ctx, &keyblock->key, enctype, &crypto);
584 ret = krb5_decrypt(ctx, crypto, usage, in->val, in->len, &kd_out);
586 ret = RXGK_SEALED_INCON;
589 ret = rx_opaque_populate(out, kd_out.data, kd_out.length);
593 krb5_crypto_destroy(ctx, crypto);
594 krb5_data_free(&kd_out);
596 krb5_free_context(ctx);
602 * Helper for derive_tk.
603 * Assumes the caller has already allocated space in 'out'.
606 PRFplus(krb5_data *out, krb5_enctype enctype, rxgk_key k0,
607 void *seed, size_t seed_len)
609 krb5_context ctx = NULL;
610 krb5_crypto crypto = NULL;
611 krb5_data prf_in, prf_out;
613 struct rxgk_keyblock *keyblock = key2keyblock(k0);
614 unsigned char *pre_key = NULL;
616 size_t desired_len = out->length;
617 afs_uint32 n_iter, iterations, dummy;
619 memset(&prf_in, 0, sizeof(prf_in));
620 memset(&prf_out, 0, sizeof(prf_out));
622 ret = krb5_init_context(&ctx);
626 ret = krb5_crypto_init(ctx, &keyblock->key, enctype, &crypto);
629 prf_in.length = sizeof(n_iter) + seed_len;
630 prf_in.data = rxi_Alloc(prf_in.length);
631 if (prf_in.data == NULL) {
632 ret = RXGK_INCONSISTENCY;
635 memcpy((unsigned char *)prf_in.data + sizeof(n_iter), seed, seed_len);
636 ret = krb5_crypto_prf_length(ctx, enctype, &block_len);
639 /* We need desired_len/block_len iterations, rounded up. */
640 iterations = (desired_len + block_len - 1) / block_len;
641 pre_key = rxi_Alloc(iterations * block_len);
642 if (pre_key == NULL) {
643 ret = RXGK_INCONSISTENCY;
647 for (n_iter = 1; n_iter <= iterations; ++n_iter) {
648 dummy = htonl(n_iter);
649 memcpy(prf_in.data, &dummy, sizeof(dummy));
650 krb5_data_free(&prf_out);
651 ret = krb5_crypto_prf(ctx, crypto, &prf_in, &prf_out);
654 memcpy(pre_key + (n_iter - 1) * block_len, prf_out.data, block_len);
656 memcpy(out->data, pre_key, desired_len);
657 out->length = desired_len;
661 krb5_crypto_destroy(ctx, crypto);
662 krb5_data_free(&prf_out);
664 krb5_free_context(ctx);
666 rxi_Free(prf_in.data, prf_in.length);
668 rxi_Free(pre_key, iterations * block_len);
677 afs_uint32 key_number;
678 } __attribute__((packed));
680 /* Our seed_data buffer that we feed into the PRF+ algorithm to generate our
681 * transport key had better be exactly 20 bytes large, to match the format of
682 * the seed data in the rxgk spec. */
683 #define RXGK_SEED_DATA_SIZE 20
686 * Compute a transport key tk given a master key k0
688 * Given a connection master key k0, derive a transport key tk from the master
689 * key and connection parameters.
691 * TK = random-to-key(PRF+(K0, L, epoch || cid || start_time || key_number))
692 * using the RFC4402 PRF+, i.e., the ordinal of the application of the
693 * pseudo-random() function is stored in a 32-bit field, not an 8-bit field
696 * @param[out] tk The derived transport key.
697 * @param[in] k0 The token master key.
698 * @param[in] epoch The rx epoch of the connection.
699 * @param[in] cid The rx connection id of the connection.
700 * @param[in] start_time The start_time of the connection.
701 * @param[in] key_number The current key number of the connection.
702 * @return rxgk error codes.
705 rxgk_derive_tk(rxgk_key *tk, rxgk_key k0, afs_uint32 epoch, afs_uint32 cid,
706 rxgkTime start_time, afs_uint32 key_number)
708 krb5_enctype enctype;
710 struct rxgk_keyblock *keyblock = key2keyblock(k0);
711 struct seed_data seed;
715 memset(&pre_key, 0, sizeof(pre_key));
716 memset(&seed, 0, sizeof(seed));
718 opr_StaticAssert(sizeof(seed) == RXGK_SEED_DATA_SIZE);
719 enctype = deref_keyblock_enctype(&keyblock->key);
720 ell = rxgk_etype_to_len(enctype);
722 return RXGK_INCONSISTENCY;
724 seed.epoch = htonl(epoch);
725 seed.cid = htonl(cid);
726 seed.time_hi = htonl((afs_int32)(start_time / ((afs_int64)1 << 32)));
727 seed.time_lo = htonl((afs_uint32)(start_time & (afs_uint64)0xffffffffu));
728 seed.key_number = htonl(key_number);
730 pre_key.data = rxi_Alloc(ell);
731 if (pre_key.data == NULL) {
732 ret = RXGK_INCONSISTENCY;
735 pre_key.length = ell;
736 ret = PRFplus(&pre_key, enctype, k0, &seed, sizeof(seed));
740 ret = rxgk_make_key(tk, pre_key.data, ell, enctype);
745 rxi_Free(pre_key.data, ell);
750 * Determine the maximum ciphertext expansion for a given enctype.
752 * @param[in] k0 The rxgk key to be used.
753 * @param[out] len_out The maximum ciphertext expansion, in octets.
754 * @return rxgk error codes.
757 rxgk_cipher_expansion(rxgk_key k0, afs_uint32 *len_out)
759 krb5_context ctx = NULL;
760 krb5_crypto crypto = NULL;
761 krb5_enctype enctype;
763 struct rxgk_keyblock *keyblock = key2keyblock(k0);
768 enctype = deref_keyblock_enctype(&keyblock->key);
769 ret = krb5_init_context(&ctx);
772 ret = krb5_crypto_init(ctx, &keyblock->key, enctype, &crypto);
775 len = krb5_crypto_overhead(ctx, crypto);
780 krb5_crypto_destroy(ctx, crypto);
782 krb5_free_context(ctx);
788 * Allocate and fill the buffer in nonce with len bytes of random data.
790 * @param[out] nonce The buffer of random data.
791 * @param[in] len The number of octets of random data to produce.
792 * @return rx error codes.
795 rxgk_nonce(RXGK_Data *nonce, afs_uint32 len)
797 if (rx_opaque_alloc(nonce, len) != 0)
798 return RXGK_INCONSISTENCY;
800 krb5_generate_random_block(nonce->val, len);