3 // libsecurity_libSecOTR
5 // Created by Mitch Adler on 1/28/11.
6 // Copyright 2011 Apple Inc. All rights reserved.
9 #include "SecOTRMath.h"
10 #include "SecOTRMathPrivate.h"
12 #include "SecOTRPacketData.h"
14 #include <AssertMacros.h>
18 #include <Security/SecRandom.h>
20 #include <corecrypto/ccsha2.h>
21 #include <corecrypto/cczp.h>
26 void cczp_init_from_bytes(cc_size n
, cczp_t zp
, size_t pSize
, const void *p
, size_t rSize
, const void* r
)
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
);
35 static pthread_once_t kOTRImportGroupData
= PTHREAD_ONCE_INIT
;
37 static cc_unit sOTRGenerator
[kOTRDHGroupUnits
];
38 static cczp_decl_n(kOTRDHGroupUnits
, sOTRGroup_zp
);
40 static void setupGroupValues()
42 __Check( kExponentiationUnits
== kOTRDHGroupUnits
);
44 cczp_init_from_bytes(kOTRDHGroupUnits
, sOTRGroup_zp
,
45 sizeof(kOTRDHGroup
), kOTRDHGroup
,
46 sizeof(kOTRDHGroup_Recip
), kOTRDHGroup_Recip
);
48 ccn_seti(kOTRDHGroupUnits
, sOTRGenerator
, kOTRGeneratorValue
);
51 void OTRExponentiate(cc_unit
* res
, const cc_unit
* base
, const cc_unit
* exponent
)
53 pthread_once(&kOTRImportGroupData
, setupGroupValues
);
55 cczp_power(sOTRGroup_zp
, res
, base
, exponent
);
58 void OTRGroupExponentiate(cc_unit
* res
, const cc_unit
* exponent
)
60 pthread_once(&kOTRImportGroupData
, setupGroupValues
);
62 OTRExponentiate(res
, sOTRGenerator
, exponent
);
66 // Random Number Generation
69 OSStatus
GetRandomBytesInLSBs(size_t bytesOfRandomness
, size_t n
, cc_unit
* place
)
71 OSStatus result
= errSecParam
;
72 require(bytesOfRandomness
* 8 <= ccn_bitsof_n(n
), fail
);
74 uint8_t randomBytes
[bytesOfRandomness
];
76 result
= SecRandomCopyBytes(kSecRandomDefault
, sizeof(randomBytes
), randomBytes
);
78 require_noerr(result
, fail
);
80 ccn_read_uint(n
, place
, sizeof(randomBytes
), randomBytes
);
82 bzero(randomBytes
, bytesOfRandomness
);
88 OSStatus
FillWithRandomBytes(size_t n
, cc_unit
* place
)
90 return GetRandomBytesInLSBs(ccn_sizeof(n
), n
, place
);
94 static const uint8_t kIVZero
[16] = { };
96 static void AES_CTR_Transform(size_t keySize
, const uint8_t* key
,
98 size_t howMuch
, const uint8_t* from
, uint8_t* to
)
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
);
104 ctr_encrypt
->ctr(ctr_ctx
, howMuch
, from
, to
);
107 void AES_CTR_HighHalf_Transform(size_t keySize
, const uint8_t* key
,
109 size_t howMuch
, const uint8_t* from
, uint8_t* to
)
111 uint8_t iv
[16] = { highHalf
>> 56, highHalf
>> 48, highHalf
>> 40, highHalf
>> 32,
112 highHalf
>> 24, highHalf
>> 16, highHalf
>> 8 , highHalf
>> 0,
115 AES_CTR_Transform(keySize
, key
, iv
, howMuch
, from
, to
);
118 void AES_CTR_IV0_Transform(size_t keySize
, const uint8_t* key
,
119 size_t howMuch
, const uint8_t* from
, uint8_t* to
)
121 AES_CTR_Transform(keySize
, key
, kIVZero
, howMuch
, from
, to
);
129 static void HashMPIWithPrefix(uint8_t byte
, cc_size sN
, const cc_unit
* s
, uint8_t* buffer
)
131 CFMutableDataRef dataToHash
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
132 CFDataAppendBytes(dataToHash
, &byte
, 1);
134 AppendMPI(dataToHash
, sN
, s
);
136 uint8_t *bytesToHash
= CFDataGetMutableBytePtr(dataToHash
);
137 CFIndex amountToHash
= CFDataGetLength(dataToHash
);
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 */
142 (void) CC_SHA256(bytesToHash
, (CC_LONG
)amountToHash
, buffer
);
144 bzero(bytesToHash
, (size_t)amountToHash
);
145 CFReleaseNull(dataToHash
);
148 void DeriveOTR256BitsFromS(KeyType whichKey
, cc_size sN
, const cc_unit
* s
, size_t keySize
, uint8_t* key
)
150 HashMPIWithPrefix(whichKey
, sN
, s
, key
);
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
)
157 uint8_t hashBuffer
[CCSHA256_OUTPUT_SIZE
];
159 HashMPIWithPrefix(whichKey
, sSize
, s
, hashBuffer
);
162 firstKeySize
= firstKeySize
> CCSHA256_OUTPUT_SIZE
/2 ? CCSHA256_OUTPUT_SIZE
/2 : firstKeySize
;
163 memcpy(firstKey
, hashBuffer
, firstKeySize
);
166 secondKeySize
= secondKeySize
> CCSHA256_OUTPUT_SIZE
/2 ? CCSHA256_OUTPUT_SIZE
/2 : secondKeySize
;
167 memcpy(secondKey
, hashBuffer
, secondKeySize
);
170 bzero(hashBuffer
, CCSHA256_OUTPUT_SIZE
);
174 void DeriveOTR64BitsFromS(KeyType whichKey
, size_t sn
, const cc_unit
* s
,
175 size_t topKeySize
, uint8_t* topKey
)
177 uint8_t hashBuffer
[CCSHA256_OUTPUT_SIZE
];
179 HashMPIWithPrefix(whichKey
, sn
, s
, hashBuffer
);
181 topKeySize
= topKeySize
> CCSHA256_OUTPUT_SIZE
/2 ? CCSHA256_OUTPUT_SIZE
/2 : topKeySize
;
182 memcpy(topKey
, hashBuffer
, topKeySize
);
184 bzero(hashBuffer
, CCSHA256_OUTPUT_SIZE
);