]> git.saurik.com Git - apple/security.git/blob - sec/Security/SecOTRMath.c
Security-55471.tar.gz
[apple/security.git] / sec / Security / SecOTRMath.c
1 //
2 // OTRMath.c
3 // libsecurity_libSecOTR
4 //
5 // Created by Mitch Adler on 1/28/11.
6 // Copyright 2011 Apple Inc. All rights reserved.
7 //
8
9 #include "SecOTRMath.h"
10 #include "SecOTRMathPrivate.h"
11
12 #include "SecOTRPacketData.h"
13
14 #include <AssertMacros.h>
15
16 #include <pthread.h>
17
18 #include <Security/SecRandom.h>
19
20 #include <corecrypto/ccsha2.h>
21 #include <corecrypto/cczp.h>
22
23 #include <limits.h>
24
25 static inline
26 void cczp_init_from_bytes(cc_size n, cczp_t zp, size_t pSize, const void *p, size_t rSize, const void* r)
27 {
28 CCZP_N(zp) = n;
29 zp.zp->mod_prime = cczp_mod;
30 ccn_read_uint(n, CCZP_PRIME(zp), pSize, p);
31 ccn_read_uint(n+1, CCZP_RECIP(zp), rSize, r);
32
33 }
34
35 static pthread_once_t kOTRImportGroupData = PTHREAD_ONCE_INIT;
36
37 static cc_unit sOTRGenerator[kOTRDHGroupUnits];
38 static cczp_decl_n(kOTRDHGroupUnits, sOTRGroup_zp);
39
40 static void setupGroupValues()
41 {
42 __Check( kExponentiationUnits == kOTRDHGroupUnits );
43
44 cczp_init_from_bytes(kOTRDHGroupUnits, sOTRGroup_zp,
45 sizeof(kOTRDHGroup), kOTRDHGroup,
46 sizeof(kOTRDHGroup_Recip), kOTRDHGroup_Recip);
47
48 ccn_seti(kOTRDHGroupUnits, sOTRGenerator, kOTRGeneratorValue);
49 }
50
51 void OTRExponentiate(cc_unit* res, const cc_unit* base, const cc_unit* exponent)
52 {
53 pthread_once(&kOTRImportGroupData, setupGroupValues);
54
55 cczp_power(sOTRGroup_zp, res, base, exponent);
56 }
57
58 void OTRGroupExponentiate(cc_unit* res, const cc_unit* exponent)
59 {
60 pthread_once(&kOTRImportGroupData, setupGroupValues);
61
62 OTRExponentiate(res, sOTRGenerator, exponent);
63 }
64
65 //
66 // Random Number Generation
67 //
68
69 OSStatus GetRandomBytesInLSBs(size_t bytesOfRandomness, size_t n, cc_unit* place)
70 {
71 OSStatus result = errSecParam;
72 require(bytesOfRandomness * 8 <= ccn_bitsof_n(n), fail);
73 {
74 uint8_t randomBytes[bytesOfRandomness];
75
76 result = SecRandomCopyBytes(kSecRandomDefault, sizeof(randomBytes), randomBytes);
77
78 require_noerr(result, fail);
79
80 ccn_read_uint(n, place, sizeof(randomBytes), randomBytes);
81
82 bzero(randomBytes, bytesOfRandomness);
83 }
84 fail:
85 return result;
86 }
87
88 OSStatus FillWithRandomBytes(size_t n, cc_unit* place)
89 {
90 return GetRandomBytesInLSBs(ccn_sizeof(n), n, place);
91 }
92
93
94 static const uint8_t kIVZero[16] = { };
95
96 static void AES_CTR_Transform(size_t keySize, const uint8_t* key,
97 const uint8_t iv[16],
98 size_t howMuch, const uint8_t* from, uint8_t* to)
99 {
100 const struct ccmode_ctr* ctr_encrypt = ccaes_ctr_crypt_mode();
101 ccctr_ctx_decl(ctr_encrypt->size, ctr_ctx);
102 ctr_encrypt->init(ctr_encrypt, ctr_ctx, keySize, key, iv);
103
104 ctr_encrypt->ctr(ctr_ctx, howMuch, from, to);
105 }
106
107 void AES_CTR_HighHalf_Transform(size_t keySize, const uint8_t* key,
108 uint64_t highHalf,
109 size_t howMuch, const uint8_t* from, uint8_t* to)
110 {
111 uint8_t iv[16] = { highHalf >> 56, highHalf >> 48, highHalf >> 40, highHalf >> 32,
112 highHalf >> 24, highHalf >> 16, highHalf >> 8 , highHalf >> 0,
113 0, 0, 0, 0,
114 0, 0, 0, 0 };
115 AES_CTR_Transform(keySize, key, iv, howMuch, from, to);
116 }
117
118 void AES_CTR_IV0_Transform(size_t keySize, const uint8_t* key,
119 size_t howMuch, const uint8_t* from, uint8_t* to)
120 {
121 AES_CTR_Transform(keySize, key, kIVZero, howMuch, from, to);
122 }
123
124
125 //
126 // Key Derivation
127 //
128
129 static void HashMPIWithPrefix(uint8_t byte, cc_size sN, const cc_unit* s, uint8_t* buffer)
130 {
131 CFMutableDataRef dataToHash = CFDataCreateMutable(kCFAllocatorDefault, 0);
132 CFDataAppendBytes(dataToHash, &byte, 1);
133
134 AppendMPI(dataToHash, sN, s);
135
136 uint8_t *bytesToHash = CFDataGetMutableBytePtr(dataToHash);
137 CFIndex amountToHash = CFDataGetLength(dataToHash);
138
139 /* 64 bits cast: amountToHash is the size of an identity +1 , which is currently hardcoded and never more than 2^32 bytes */
140 assert((unsigned long)amountToHash<UINT32_MAX); /* Debug check, Correct as long as CFIndex is a signed long and CC_LONG is a uint32_t */
141
142 (void) CC_SHA256(bytesToHash, (CC_LONG)amountToHash, buffer);
143
144 bzero(bytesToHash, (size_t)amountToHash);
145 CFReleaseNull(dataToHash);
146 }
147
148 void DeriveOTR256BitsFromS(KeyType whichKey, cc_size sN, const cc_unit* s, size_t keySize, uint8_t* key)
149 {
150 HashMPIWithPrefix(whichKey, sN, s, key);
151 }
152
153 void DeriveOTR128BitPairFromS(KeyType whichKey, size_t sSize, const cc_unit* s,
154 size_t firstKeySize, uint8_t* firstKey,
155 size_t secondKeySize, uint8_t* secondKey)
156 {
157 uint8_t hashBuffer[CCSHA256_OUTPUT_SIZE];
158
159 HashMPIWithPrefix(whichKey, sSize, s, hashBuffer);
160
161 if (firstKey) {
162 firstKeySize = firstKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : firstKeySize;
163 memcpy(firstKey, hashBuffer, firstKeySize);
164 }
165 if (secondKey) {
166 secondKeySize = secondKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : secondKeySize;
167 memcpy(secondKey, hashBuffer, secondKeySize);
168 }
169
170 bzero(hashBuffer, CCSHA256_OUTPUT_SIZE);
171
172 }
173
174 void DeriveOTR64BitsFromS(KeyType whichKey, size_t sn, const cc_unit* s,
175 size_t topKeySize, uint8_t* topKey)
176 {
177 uint8_t hashBuffer[CCSHA256_OUTPUT_SIZE];
178
179 HashMPIWithPrefix(whichKey, sn, s, hashBuffer);
180
181 topKeySize = topKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : topKeySize;
182 memcpy(topKey, hashBuffer, topKeySize);
183
184 bzero(hashBuffer, CCSHA256_OUTPUT_SIZE);
185 }
186