OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 /* Copyright(c) 2013, Intel Corp. */ | 4 /* Copyright(c) 2013, Intel Corp. */ |
5 | 5 |
6 /* Wrapper functions for Intel optimized implementation of AES-GCM */ | 6 /* Wrapper functions for Intel optimized implementation of AES-GCM */ |
7 | 7 |
8 #ifdef USE_HW_AES | 8 #ifdef USE_HW_AES |
9 | 9 |
10 #ifdef FREEBL_NO_DEPEND | 10 #ifdef FREEBL_NO_DEPEND |
(...skipping 21 matching lines...) Expand all Loading... |
32 unsigned char Htbl[16*AES_BLOCK_SIZE]; | 32 unsigned char Htbl[16*AES_BLOCK_SIZE]; |
33 unsigned char X0[AES_BLOCK_SIZE]; | 33 unsigned char X0[AES_BLOCK_SIZE]; |
34 unsigned char T[AES_BLOCK_SIZE]; | 34 unsigned char T[AES_BLOCK_SIZE]; |
35 unsigned char CTR[AES_BLOCK_SIZE]; | 35 unsigned char CTR[AES_BLOCK_SIZE]; |
36 AESContext *aes_context; | 36 AESContext *aes_context; |
37 unsigned long tagBits; | 37 unsigned long tagBits; |
38 unsigned long Alen; | 38 unsigned long Alen; |
39 unsigned long Mlen; | 39 unsigned long Mlen; |
40 }; | 40 }; |
41 | 41 |
42 intel_AES_GCMContext *intel_AES_GCM_CreateContext(void *context, | 42 intel_AES_GCMContext *intel_AES_GCM_CreateContext(void *context, |
43 freeblCipherFunc cipher, | 43 freeblCipherFunc cipher, |
44 const unsigned char *params, | 44 const unsigned char *params, |
45 unsigned int blocksize) | 45 unsigned int blocksize) |
46 { | 46 { |
47 intel_AES_GCMContext *gcm = NULL; | 47 intel_AES_GCMContext *gcm = NULL; |
48 AESContext *aes = (AESContext*)context; | 48 AESContext *aes = (AESContext*)context; |
49 const CK_GCM_PARAMS *gcmParams = (const CK_GCM_PARAMS *)params; | 49 const CK_GCM_PARAMS *gcmParams = (const CK_GCM_PARAMS *)params; |
50 unsigned char buff[AES_BLOCK_SIZE]; /* aux buffer */ | 50 unsigned char buff[AES_BLOCK_SIZE]; /* aux buffer */ |
51 | 51 |
52 int IV_whole_len = gcmParams->ulIvLen&(~0xf); | 52 unsigned long IV_whole_len = gcmParams->ulIvLen & (~0xful); |
53 int IV_remainder_len = gcmParams->ulIvLen&0xf; | 53 unsigned int IV_remainder_len = gcmParams->ulIvLen & 0xful; |
54 int AAD_whole_len = gcmParams->ulAADLen&(~0xf); | 54 unsigned long AAD_whole_len = gcmParams->ulAADLen & (~0xful); |
55 int AAD_remainder_len = gcmParams->ulAADLen&0xf; | 55 unsigned int AAD_remainder_len = gcmParams->ulAADLen & 0xful; |
56 | 56 |
57 __m128i BSWAP_MASK = _mm_setr_epi8(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0); | 57 __m128i BSWAP_MASK = _mm_setr_epi8(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0); |
58 __m128i ONE = _mm_set_epi32(0,0,0,1); | 58 __m128i ONE = _mm_set_epi32(0,0,0,1); |
59 unsigned int j; | 59 unsigned int j; |
60 SECStatus rv; | 60 SECStatus rv; |
61 | 61 |
62 if (blocksize != AES_BLOCK_SIZE) { | 62 if (blocksize != AES_BLOCK_SIZE) { |
63 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | 63 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
64 return NULL; | 64 return NULL; |
65 } | 65 } |
66 gcm = PORT_ZNew(intel_AES_GCMContext); | 66 gcm = PORT_ZNew(intel_AES_GCMContext); |
67 | 67 |
68 if (gcm == NULL) { | 68 if (gcm == NULL) { |
69 return NULL; | 69 return NULL; |
70 } | 70 } |
| 71 |
71 /* initialize context fields */ | 72 /* initialize context fields */ |
72 gcm->aes_context = aes; | 73 gcm->aes_context = aes; |
73 gcm->tagBits = gcmParams->ulTagBits; | 74 gcm->tagBits = gcmParams->ulTagBits; |
74 gcm->Alen = 0; | 75 gcm->Alen = 0; |
75 gcm->Mlen = 0; | 76 gcm->Mlen = 0; |
| 77 |
76 /* first prepare H and its derivatives for ghash */ | 78 /* first prepare H and its derivatives for ghash */ |
77 intel_aes_gcmINIT(gcm->Htbl, (unsigned char*)aes->expandedKey, aes->Nr); | 79 intel_aes_gcmINIT(gcm->Htbl, (unsigned char*)aes->expandedKey, aes->Nr); |
78 /* Initial TAG value is zero*/ | 80 |
| 81 /* Initial TAG value is zero */ |
79 _mm_storeu_si128((__m128i*)gcm->T, _mm_setzero_si128()); | 82 _mm_storeu_si128((__m128i*)gcm->T, _mm_setzero_si128()); |
80 _mm_storeu_si128((__m128i*)gcm->X0, _mm_setzero_si128()); | 83 _mm_storeu_si128((__m128i*)gcm->X0, _mm_setzero_si128()); |
| 84 |
81 /* Init the counter */ | 85 /* Init the counter */ |
82 if(gcmParams->ulIvLen == 12) { | 86 if (gcmParams->ulIvLen == 12) { |
83 _mm_storeu_si128((__m128i*)gcm->CTR, _mm_setr_epi32(((unsigned int*)gcmP
arams->pIv)[0], ((unsigned int*)gcmParams->pIv)[1], ((unsigned int*)gcmParams->p
Iv)[2], 0x01000000)); | 87 _mm_storeu_si128((__m128i*)gcm->CTR, |
| 88 _mm_setr_epi32(((unsigned int*)gcmParams->pIv)[0], |
| 89 ((unsigned int*)gcmParams->pIv)[1], |
| 90 ((unsigned int*)gcmParams->pIv)[2], |
| 91 0x01000000)); |
84 } else { | 92 } else { |
85 /* If IV size is not 96 bits, then the initial counter value is GHASH of
the IV */ | 93 /* If IV size is not 96 bits, then the initial counter value is GHASH |
| 94 * of the IV */ |
86 intel_aes_gcmAAD(gcm->Htbl, gcmParams->pIv, IV_whole_len, gcm->T); | 95 intel_aes_gcmAAD(gcm->Htbl, gcmParams->pIv, IV_whole_len, gcm->T); |
| 96 |
87 /* Partial block */ | 97 /* Partial block */ |
88 if(IV_remainder_len) { | 98 if (IV_remainder_len) { |
89 PORT_Memset(buff, 0, AES_BLOCK_SIZE); | 99 PORT_Memset(buff, 0, AES_BLOCK_SIZE); |
90 PORT_Memcpy(buff, gcmParams->pIv + IV_whole_len, IV_remainder_len); | 100 PORT_Memcpy(buff, gcmParams->pIv + IV_whole_len, IV_remainder_len); |
91 intel_aes_gcmAAD(gcm->Htbl, buff, AES_BLOCK_SIZE, gcm->T); | 101 intel_aes_gcmAAD(gcm->Htbl, buff, AES_BLOCK_SIZE, gcm->T); |
92 } | 102 } |
93 | 103 |
94 intel_aes_gcmTAG | 104 intel_aes_gcmTAG( |
95 ( | |
96 gcm->Htbl, | 105 gcm->Htbl, |
97 gcm->T, | 106 gcm->T, |
98 gcmParams->ulIvLen, | 107 gcmParams->ulIvLen, |
99 0, | 108 0, |
100 gcm->X0, | 109 gcm->X0, |
101 gcm->CTR | 110 gcm->CTR); |
102 ); | 111 |
103 /* TAG should be zero again */ | 112 /* TAG should be zero again */ |
104 _mm_storeu_si128((__m128i*)gcm->T, _mm_setzero_si128()); | 113 _mm_storeu_si128((__m128i*)gcm->T, _mm_setzero_si128()); |
105 } | 114 } |
106 /* Encrypt the initial counter, will be used to encrypt the GHASH value, in
the end */ | 115 |
107 rv = (*cipher)(context, gcm->X0, &j, AES_BLOCK_SIZE, gcm->CTR, AES_BLOCK_SIZ
E, AES_BLOCK_SIZE); | 116 /* Encrypt the initial counter, will be used to encrypt the GHASH value, |
| 117 * in the end */ |
| 118 rv = (*cipher)(context, gcm->X0, &j, AES_BLOCK_SIZE, gcm->CTR, |
| 119 AES_BLOCK_SIZE, AES_BLOCK_SIZE); |
108 if (rv != SECSuccess) { | 120 if (rv != SECSuccess) { |
109 goto loser; | 121 goto loser; |
110 } | 122 } |
| 123 |
111 /* Promote the counter by 1 */ | 124 /* Promote the counter by 1 */ |
112 _mm_storeu_si128((__m128i*)gcm->CTR, _mm_shuffle_epi8(_mm_add_epi32(ONE, _mm
_shuffle_epi8(_mm_loadu_si128((__m128i*)gcm->CTR), BSWAP_MASK)), BSWAP_MASK)); | 125 _mm_storeu_si128((__m128i*)gcm->CTR, _mm_shuffle_epi8(_mm_add_epi32(ONE, _mm
_shuffle_epi8(_mm_loadu_si128((__m128i*)gcm->CTR), BSWAP_MASK)), BSWAP_MASK)); |
113 | 126 |
114 /* Now hash AAD - it would actually make sense to seperate the context creat
ion from the AAD, | 127 /* Now hash AAD - it would actually make sense to seperate the context |
115 * because that would allow to reuse the H, which only changes when the AES
key changes, | 128 * creation from the AAD, because that would allow to reuse the H, which |
116 * and not every package, like the IV and AAD */ | 129 * only changes when the AES key changes, and not every package, like the |
| 130 * IV and AAD */ |
117 intel_aes_gcmAAD(gcm->Htbl, gcmParams->pAAD, AAD_whole_len, gcm->T); | 131 intel_aes_gcmAAD(gcm->Htbl, gcmParams->pAAD, AAD_whole_len, gcm->T); |
118 if(AAD_remainder_len) { | 132 if (AAD_remainder_len) { |
119 PORT_Memset(buff, 0, AES_BLOCK_SIZE); | 133 PORT_Memset(buff, 0, AES_BLOCK_SIZE); |
120 PORT_Memcpy(buff, gcmParams->pAAD + AAD_whole_len, AAD_remainder_len); | 134 PORT_Memcpy(buff, gcmParams->pAAD + AAD_whole_len, AAD_remainder_len); |
121 intel_aes_gcmAAD(gcm->Htbl, buff, AES_BLOCK_SIZE, gcm->T); | 135 intel_aes_gcmAAD(gcm->Htbl, buff, AES_BLOCK_SIZE, gcm->T); |
122 } | 136 } |
123 gcm->Alen += gcmParams->ulAADLen; | 137 gcm->Alen += gcmParams->ulAADLen; |
124 return gcm; | 138 return gcm; |
125 | 139 |
126 loser: | 140 loser: |
127 if (gcm) { | 141 if (gcm) { |
128 PORT_Free(gcm); | 142 PORT_Free(gcm); |
129 } | 143 } |
130 return NULL; | 144 return NULL; |
131 } | 145 } |
132 | 146 |
133 void intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit) | 147 void intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit) |
134 { | 148 { |
135 if (freeit) { | 149 if (freeit) { |
136 PORT_Free(gcm); | 150 PORT_Free(gcm); |
137 } | 151 } |
138 } | 152 } |
139 | 153 |
140 SECStatus intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm, | 154 SECStatus intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm, |
141 unsigned char *outbuf, | 155 unsigned char *outbuf, |
142 unsigned int *outlen, unsigned int maxout, | 156 unsigned int *outlen, unsigned int maxout, |
143 const unsigned char *inbuf, unsigned int inlen, | 157 const unsigned char *inbuf, unsigned int inlen, |
144 unsigned int blocksize) | 158 unsigned int blocksize) |
145 { | 159 { |
146 unsigned int tagBytes; | 160 unsigned int tagBytes; |
147 unsigned char T[AES_BLOCK_SIZE]; | 161 unsigned char T[AES_BLOCK_SIZE]; |
148 int j; | 162 unsigned int j; |
149 | 163 |
150 tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE-1)) / PR_BITS_PER_BYTE; | 164 tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE; |
151 if (UINT_MAX - inlen < tagBytes) { | 165 if (UINT_MAX - inlen < tagBytes) { |
152 PORT_SetError(SEC_ERROR_INPUT_LEN); | 166 PORT_SetError(SEC_ERROR_INPUT_LEN); |
153 return SECFailure; | 167 return SECFailure; |
154 } | 168 } |
155 if (maxout < inlen + tagBytes) { | 169 if (maxout < inlen + tagBytes) { |
156 *outlen = inlen + tagBytes; | 170 *outlen = inlen + tagBytes; |
157 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | 171 PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
158 return SECFailure; | 172 return SECFailure; |
159 } | 173 } |
160 | 174 |
161 intel_aes_gcmENC( | 175 intel_aes_gcmENC( |
162 inbuf, | 176 inbuf, |
163 outbuf, | 177 outbuf, |
164 gcm, | 178 gcm, |
165 inlen); | 179 inlen); |
166 | 180 |
167 gcm->Mlen += inlen; | 181 gcm->Mlen += inlen; |
168 | 182 |
169 intel_aes_gcmTAG( | 183 intel_aes_gcmTAG( |
170 gcm->Htbl, | 184 gcm->Htbl, |
171 gcm->T, | 185 gcm->T, |
172 gcm->Mlen, | 186 gcm->Mlen, |
173 gcm->Alen, | 187 gcm->Alen, |
174 gcm->X0, | 188 gcm->X0, |
175 T); | 189 T); |
176 | 190 |
177 *outlen = inlen + tagBytes; | 191 *outlen = inlen + tagBytes; |
178 | 192 |
179 for(j=0; j<tagBytes; j++) | 193 for (j = 0; j < tagBytes; j++) { |
180 { | 194 outbuf[inlen + j] = T[j]; |
181 outbuf[inlen+j] = T[j]; | |
182 } | 195 } |
183 return SECSuccess; | 196 return SECSuccess; |
184 } | 197 } |
185 | 198 |
186 SECStatus intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm, | 199 SECStatus intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm, |
187 unsigned char *outbuf, | 200 unsigned char *outbuf, |
188 unsigned int *outlen, unsigned int maxout, | 201 unsigned int *outlen, unsigned int maxout, |
189 const unsigned char *inbuf, unsigned int inlen, | 202 const unsigned char *inbuf, unsigned int inlen, |
190 unsigned int blocksize) | 203 unsigned int blocksize) |
191 { | 204 { |
192 unsigned int tagBytes; | 205 unsigned int tagBytes; |
193 unsigned char T[AES_BLOCK_SIZE]; | 206 unsigned char T[AES_BLOCK_SIZE]; |
194 const unsigned char *intag; | 207 const unsigned char *intag; |
195 | 208 |
196 tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE-1)) / PR_BITS_PER_BYTE; | 209 tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE; |
197 | 210 |
198 /* get the authentication block */ | 211 /* get the authentication block */ |
199 if (inlen < tagBytes) { | 212 if (inlen < tagBytes) { |
200 PORT_SetError(SEC_ERROR_INPUT_LEN); | 213 PORT_SetError(SEC_ERROR_INPUT_LEN); |
201 return SECFailure; | 214 return SECFailure; |
202 } | 215 } |
203 | 216 |
204 inlen -= tagBytes; | 217 inlen -= tagBytes; |
205 intag = inbuf + inlen; | 218 intag = inbuf + inlen; |
206 | 219 |
207 if (maxout < inlen) { | 220 if (maxout < inlen) { |
(...skipping 23 matching lines...) Expand all Loading... |
231 /* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */ | 244 /* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */ |
232 PORT_SetError(SEC_ERROR_BAD_DATA); | 245 PORT_SetError(SEC_ERROR_BAD_DATA); |
233 return SECFailure; | 246 return SECFailure; |
234 } | 247 } |
235 *outlen = inlen; | 248 *outlen = inlen; |
236 | 249 |
237 return SECSuccess; | 250 return SECSuccess; |
238 } | 251 } |
239 | 252 |
240 #endif | 253 #endif |
OLD | NEW |