diff options
Diffstat (limited to 'usr/src/lib/libkmsagent/common/ieee80211_crypto.c')
| -rw-r--r-- | usr/src/lib/libkmsagent/common/ieee80211_crypto.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/usr/src/lib/libkmsagent/common/ieee80211_crypto.c b/usr/src/lib/libkmsagent/common/ieee80211_crypto.c new file mode 100644 index 0000000000..367e8ac932 --- /dev/null +++ b/usr/src/lib/libkmsagent/common/ieee80211_crypto.c @@ -0,0 +1,201 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +#if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10) +#include "rijndael.h" +#else +#include <stdlib.h> +#include <aes_impl.h> +#endif + +#ifdef METAWARE +#include "sizet.h" +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +#include <string.h> +#else +#ifndef WIN32 +#include <strings.h> +#endif +#endif + +#include "KMSAgentAESKeyWrap.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef WIN32 +#define ovbcopy(x, y, z) memmove(y, x, z); +#else +#define ovbcopy(x, y, z) bcopy(x, y, z); +#endif + +#ifndef K_SOLARIS_PLATFORM +/* similar to iovec except that it accepts const pointers */ +struct vector { + const void *base; + size_t len; +}; + +#ifdef METAWARE +#define bcopy(s1, s2, n) memcpy(s2, s1, n) +#endif + +/* + * AES Key Wrap (see RFC 3394). + */ +#endif /* K_SOLARIS_PLATFORM */ + +static const uint8_t aes_key_wrap_iv[8] = + { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 }; + +void aes_key_wrap (const uint8_t *kek, + size_t kek_len, + const uint8_t *pt, + size_t len, + uint8_t *ct) +{ +#if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10) + rijndael_ctx ctx; +#else + void *ks; + size_t ks_size; +#endif + uint8_t *a, *r, ar[16], t, b[16]; + size_t i; + int j; + + /* + * Only allow lengths for 't' values that fit within a byte. This + * covers all reasonable uses of AES Key Wrap + */ + if (len > (255 / 6)) { + return; + } + + /* allow ciphertext and plaintext to overlap (ct == pt) */ + ovbcopy(pt, ct + 8, len * 8); + + a = ct; + memcpy(a, aes_key_wrap_iv, 8); /* default IV */ + +#if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10) + rijndael_set_key_enc_only(&ctx, (uint8_t *)kek, kek_len * 8); +#else + ks = aes_alloc_keysched(&ks_size, 0); + if (ks == NULL) + return; + aes_init_keysched(kek, kek_len * 8, ks); +#endif + + for (j = 0, t = 1; j < 6; j++) { + r = ct + 8; + for (i = 0; i < len; i++, t++) { + memcpy(ar, a, 8); + memcpy(ar + 8, r, 8); +#if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10) + rijndael_encrypt(&ctx, ar, b); +#else + (void) aes_encrypt_block(ks, ar, b); +#endif + + b[7] ^= t; + memcpy(a, &b[0], 8); + memcpy(r, &b[8], 8); + + r += 8; + } + } +#if defined(K_SOLARIS_PLATFORM) && !defined(SOLARIS10) + free(ks); +#endif +} + +int aes_key_unwrap (const uint8_t *kek, + size_t kek_len, + const uint8_t *ct, + uint8_t *pt, + size_t len) +{ +#if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10) + rijndael_ctx ctx; +#else + void *ks; + size_t ks_size; +#endif + uint8_t a[8], *r, b[16], t, ar[16]; + size_t i; + int j; + + /* + * Only allow lengths for 't' values that fit within a byte. This + * covers all reasonable uses of AES Key Wrap + */ + if (len > (255 / 6)) { + return (-1); + } + + memcpy(a, ct, 8); + /* allow ciphertext and plaintext to overlap (ct == pt) */ + ovbcopy(ct + 8, pt, len * 8); + +#if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10) + rijndael_set_key(&ctx, (uint8_t *)kek, kek_len * 8); +#else + ks = aes_alloc_keysched(&ks_size, 0); + if (ks == NULL) + return (-1); + aes_init_keysched(kek, kek_len * 8, ks); +#endif + + for (j = 0, t = 6 * len; j < 6; j++) { + r = pt + (len - 1) * 8; + for (i = 0; i < len; i++, t--) { + memcpy(&ar[0], a, 8); + ar[7] ^= t; + memcpy(&ar[8], r, 8); +#if !defined(K_SOLARIS_PLATFORM) || defined(SOLARIS10) + rijndael_decrypt(&ctx, ar, b); +#else + (void) aes_decrypt_block(ks, ar, b); +#endif + memcpy(a, b, 8); + memcpy(r, b + 8, 8); + r -= 8; + } + } +#if defined(K_SOLARIS_PLATFORM) && !defined(SOLARIS10) + free(ks); +#endif + + return memcmp(a, aes_key_wrap_iv, 8) != 0; +} |
