Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259/* * Copyright (c) 2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */
#include "CommonSymmetricKeywrap.h"#include <AssertMacros.h>#include <stdint.h>#include <libkern/OSByteOrder.h>
static const uint8_t rfc3394_iv_data[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
const uint8_t* CCrfc3394_iv = rfc3394_iv_data;const size_t CCrfc3394_ivLen = sizeof(rfc3394_iv_data);
static uint64_t pack64(uint8_t *iv, size_t ivLen){ uint64_t retval; int i; for(i=0, retval=0; i<8; i++) retval = (retval<<8) + iv[i]; return retval;}
#if KERNEL
#include <crypto/aes.h>#include <libkern/OSByteOrder.h>
#define AES128_KEK 1#define AES192_KEK 0#define AES256_KEK 0
#define debug kprintf
static bool aes_operation(bool encrypt, const uint8_t *kek, size_t kek_len, uint8_t *block){ uint64_t iv[2] = { 0 };
if (encrypt) { aes_encrypt_ctx encrypt_ctx[1]; switch(kek_len) {#if AES128_KEK case 16: aes_encrypt_key128(kek, encrypt_ctx); break;#endif#if AES192_KEK case 24: aes_encrypt_key192(kek, encrypt_ctx); break;#endif#if AES256_KEK case 32: aes_encrypt_key256(kek, encrypt_ctx); break;#endif default: return false; } aes_encrypt_cbc(block, (uint8_t*)iv, 1, block, encrypt_ctx); } else { aes_decrypt_ctx decrypt_ctx[1]; switch(kek_len) {#if AES128_KEK case 16: aes_decrypt_key128(kek, decrypt_ctx); break;#endif#if AES192_KEK case 24: aes_decrypt_key192(kek, decrypt_ctx); break;#endif#if AES256_KEK case 32: aes_decrypt_key256(kek, decrypt_ctx); break;#endif default: return false; } aes_decrypt_cbc(block, (uint8_t*)iv, 1, block, decrypt_ctx); }
return true;}
#else
#include "CommonCryptor.h"
#define debug printf
static bool aes_operation(bool encrypt, const uint8_t *kek, size_t kek_len, uint8_t *block){ uint64_t iv[2] = { 0 }; size_t bytes_moved = 0;
return (0 == CCCrypt(encrypt? kCCEncrypt : kCCDecrypt, kCCAlgorithmAES128, 0, kek, kek_len, iv, block, kCCBlockSizeAES128, block, kCCBlockSizeAES128, &bytes_moved));}#endif
/* 1) Initialize variables.
Set A = IV, an initial value (see 2.2.3) For i = 1 to n R[i] = P[i]
2) Calculate intermediate values.
For j = 0 to 5 For i=1 to n B = AES(K, A | R[i]) A = MSB(64, B) ^ t where t = (n x j)+i R[i] = LSB(64, B)
3) Output the results.
Set C[0] = A For i = 1 to n C[i] = R[i]
http://www.faqs.org/rfcs/rfc3394.html */
int CCSymmetricKeyWrap( CCWrappingAlgorithm algorithm, const uint8_t *iv, const size_t ivLen, const uint8_t *kek, size_t kekLen, const uint8_t *rawKey, size_t rawKeyLen, uint8_t *wrappedKey, size_t *wrappedKeyLen){ uint32_t n = rawKeyLen / 8; /* key size in 64 bit blocks */ uint64_t (*R)[2]; /* R is a two-dimensional array, with n rows of 2 columns */ int i, j, err; // allocate R R = calloc(n, sizeof(uint64_t[2])); require_action(R, out, err = -1); // don't wrap with something smaller require_action(rawKeyLen >= kekLen, out, err = -1); // kek multiple of 64 bits: 128, 192, 256 require_action(kekLen == 16 || kekLen == 24 || kekLen == 32, out, err = -1); // wrapped_key_len 64 bits larger than key_len require_action(wrappedKeyLen && (*wrappedKeyLen >= rawKeyLen + 64/8), out, err = -1);
// R[0][1] = P[0] ... R[1][n-1] = P[n-1] for (i = 0; i < n; i++) memcpy(&R[i][1], rawKey + (64/8) * i, (64/8));
uint64_t kek_iv = pack64(iv, ivLen); R[0][0] = kek_iv;
for (j = 0; j < 6; j++) { for (i = 0; i < n; i++) { require_action(aes_operation(true, kek, kekLen, (uint8_t*)&R[i][0]), out, err = -1); R[(i + 1) % n][0] = R[i][0] ^ _OSSwapInt64((n*j)+i+1); } } // write output memcpy(wrappedKey, &R[0][0], 8); for (i = 0; i < n; i++) memcpy(wrappedKey + 8 + i * 8, &R[i][1], 8);
err = 0;out: if (R) free(R); return err;}
int CCSymmetricKeyUnwrap( CCWrappingAlgorithm algorithm, const uint8_t *iv, const size_t ivLen, const uint8_t *kek, size_t kekLen, const uint8_t *wrappedKey, size_t wrappedKeyLen, uint8_t *rawKey, size_t *rawKeyLen){ uint32_t n = wrappedKeyLen/8 - 1; /* raw key size in 64 bit blocks */ uint64_t (*R)[2]; /* R is a two-dimensional array, with n rows of 2 columns */ int i, j, err;
// allocate R R = calloc(n, sizeof(uint64_t[2])); require_action(R, out, err = -1); // kek multiple of 64 bits: 128, 192, 256 require_action(kekLen == 16 || kekLen == 32, out, err = -1); // wrapped_key_len 64 bits larger than key_len require_action(rawKeyLen && (*rawKeyLen >= wrappedKeyLen - 64/8), out, err = -1);
// R[0][1] = C[0] ... R[1][n-1] = C[n-1] memcpy(&R[0][0], wrappedKey, 64/8); for (i = 0; i < n; i++) memcpy(&R[i][1], wrappedKey + (64/8) * (i+1), 64/8);
for (j = 5; j >= 0; j--) { for (i = n - 1; i >= 0; i--) { R[i][0] = R[(i + 1) % n][0] ^ _OSSwapInt64((n*j)+i+1); require_action(aes_operation(false, kek, kekLen, (uint8_t*)&R[i][0]), out, err = -1); } }
uint64_t kek_iv = pack64(iv, ivLen);
// R[0][0] == iv? require_action(R[0][0] == kek_iv, out, err = -1);
// write output for (i = 0; i < n; i++) memcpy(rawKey + i * 8, &R[i][1], 8);
// clean all stack variables
err = 0; out: if (R) free(R); return err;}
size_tCCSymmetricWrappedSize( CCWrappingAlgorithm algorithm, size_t rawKeyLen){ return (rawKeyLen + 8);}
size_tCCSymmetricUnwrappedSize( CCWrappingAlgorithm algorithm, size_t wrappedKeyLen){ return (wrappedKeyLen - 8);}