]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecOTRMath.c
Security-58286.1.32.tar.gz
[apple/security.git] / OSX / sec / Security / SecOTRMath.c
1 /*
2 * Copyright (c) 2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 #include "SecOTRMath.h"
26
27 #include "SecOTRPacketData.h"
28
29 #include <utilities/SecCFWrappers.h>
30 #include <AssertMacros.h>
31
32 #include <pthread.h>
33
34 #include <Security/SecRandom.h>
35
36 #include <corecrypto/ccsha2.h>
37 #include <corecrypto/cczp.h>
38 #include <corecrypto/ccdh_gp.h>
39
40 #include <limits.h>
41
42 //
43 // Random Number Generation
44 //
45
46 OSStatus GetRandomBytesInLSBs(size_t bytesOfRandomness, size_t n, cc_unit* place)
47 {
48 OSStatus result = errSecParam;
49 require(bytesOfRandomness * 8 <= ccn_bitsof_n(n), fail);
50 {
51 uint8_t randomBytes[bytesOfRandomness];
52
53 result = SecRandomCopyBytes(kSecRandomDefault, sizeof(randomBytes), randomBytes);
54
55 require_noerr(result, fail);
56
57 ccn_read_uint(n, place, sizeof(randomBytes), randomBytes);
58
59 bzero(randomBytes, bytesOfRandomness);
60 }
61 fail:
62 return result;
63 }
64
65 OSStatus FillWithRandomBytes(size_t n, cc_unit* place)
66 {
67 return GetRandomBytesInLSBs(ccn_sizeof(n), n, place);
68 }
69
70
71 static const uint8_t kIVZero[16] = { };
72
73 static void AES_CTR_Transform(size_t keySize, const uint8_t* key,
74 const uint8_t iv[16],
75 size_t howMuch, const uint8_t* from, uint8_t* to)
76 {
77 const struct ccmode_ctr* ctr_encrypt = ccaes_ctr_crypt_mode();
78 ccctr_ctx_decl(ctr_encrypt->size, ctr_ctx);
79 ctr_encrypt->init(ctr_encrypt, ctr_ctx, keySize, key, iv);
80
81 ctr_encrypt->ctr(ctr_ctx, howMuch, from, to);
82 }
83
84 void AES_CTR_HighHalf_Transform(size_t keySize, const uint8_t* key,
85 uint64_t highHalf,
86 size_t howMuch, const uint8_t* from, uint8_t* to)
87 {
88 uint8_t iv[16] = { highHalf >> 56, highHalf >> 48, highHalf >> 40, highHalf >> 32,
89 highHalf >> 24, highHalf >> 16, highHalf >> 8 , highHalf >> 0,
90 0, 0, 0, 0,
91 0, 0, 0, 0 };
92 AES_CTR_Transform(keySize, key, iv, howMuch, from, to);
93 }
94
95 void AES_CTR_IV0_Transform(size_t keySize, const uint8_t* key,
96 size_t howMuch, const uint8_t* from, uint8_t* to)
97 {
98 AES_CTR_Transform(keySize, key, kIVZero, howMuch, from, to);
99 }
100
101
102 //
103 // Key Derivation
104 //
105
106 static void HashMPIWithPrefix(uint8_t byte, cc_size sN, const cc_unit* s, uint8_t* buffer)
107 {
108 CFMutableDataRef dataToHash = CFDataCreateMutable(kCFAllocatorDefault, 0);
109 CFDataAppendBytes(dataToHash, &byte, 1);
110
111 AppendMPI(dataToHash, sN, s);
112
113 uint8_t *bytesToHash = CFDataGetMutableBytePtr(dataToHash);
114 CFIndex amountToHash = CFDataGetLength(dataToHash);
115
116 /* 64 bits cast: amountToHash is the size of an identity +1 , which is currently hardcoded and never more than 2^32 bytes */
117 assert((unsigned long)amountToHash<UINT32_MAX); /* Debug check, Correct as long as CFIndex is a signed long and CC_LONG is a uint32_t */
118
119 (void) CC_SHA256(bytesToHash, (CC_LONG)amountToHash, buffer);
120
121 bzero(bytesToHash, (size_t)amountToHash);
122 CFReleaseNull(dataToHash);
123 }
124
125 void DeriveOTR256BitsFromS(KeyType whichKey, cc_size sN, const cc_unit* s, size_t keySize, uint8_t* key)
126 {
127 HashMPIWithPrefix(whichKey, sN, s, key);
128 }
129
130 void DeriveOTR128BitPairFromS(KeyType whichKey, size_t sSize, const cc_unit* s,
131 size_t firstKeySize, uint8_t* firstKey,
132 size_t secondKeySize, uint8_t* secondKey)
133 {
134 uint8_t hashBuffer[CCSHA256_OUTPUT_SIZE];
135
136 HashMPIWithPrefix(whichKey, sSize, s, hashBuffer);
137
138 if (firstKey) {
139 firstKeySize = firstKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : firstKeySize;
140 memcpy(firstKey, hashBuffer, firstKeySize);
141 }
142 if (secondKey) {
143 secondKeySize = secondKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : secondKeySize;
144 memcpy(secondKey, hashBuffer, secondKeySize);
145 }
146
147 bzero(hashBuffer, CCSHA256_OUTPUT_SIZE);
148
149 }
150
151 void DeriveOTR64BitsFromS(KeyType whichKey, size_t sn, const cc_unit* s,
152 size_t topKeySize, uint8_t* topKey)
153 {
154 uint8_t hashBuffer[CCSHA256_OUTPUT_SIZE];
155
156 HashMPIWithPrefix(whichKey, sn, s, hashBuffer);
157
158 topKeySize = topKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : topKeySize;
159 memcpy(topKey, hashBuffer, topKeySize);
160
161 bzero(hashBuffer, CCSHA256_OUTPUT_SIZE);
162 }
163