|
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 |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #ifdef FREEBL_NO_DEPEND |
|
6 #include "stubs.h" |
|
7 #endif |
|
8 #include "prtypes.h" |
|
9 #include "secerr.h" |
|
10 #include "pkcs11t.h" |
|
11 #include "blapi.h" |
|
12 #include "hasht.h" |
|
13 #include "plhash.h" |
|
14 #include "nsslowhash.h" |
|
15 |
|
16 /* FIPS preprocessor directives for message digests */ |
|
17 #define FIPS_KNOWN_HASH_MESSAGE_LENGTH 64 /* 512-bits */ |
|
18 |
|
19 /* Known Hash Message (512-bits). Used for all hashes (incl. SHA-N [N>1]). */ |
|
20 static const PRUint8 known_hash_message[] = { |
|
21 "The test message for the MD2, MD5, and SHA-1 hashing algorithms." }; |
|
22 |
|
23 static CK_RV |
|
24 freebl_fips_MD2_PowerUpSelfTest( void ) |
|
25 { |
|
26 /* MD2 Known Digest Message (128-bits). */ |
|
27 static const PRUint8 md2_known_digest[] = { |
|
28 0x41,0x5a,0x12,0xb2,0x3f,0x28,0x97,0x17, |
|
29 0x0c,0x71,0x4e,0xcc,0x40,0xc8,0x1d,0x1b}; |
|
30 |
|
31 /* MD2 variables. */ |
|
32 MD2Context * md2_context; |
|
33 unsigned int md2_bytes_hashed; |
|
34 PRUint8 md2_computed_digest[MD2_LENGTH]; |
|
35 |
|
36 |
|
37 /***********************************************/ |
|
38 /* MD2 Single-Round Known Answer Hashing Test. */ |
|
39 /***********************************************/ |
|
40 |
|
41 md2_context = MD2_NewContext(); |
|
42 |
|
43 if( md2_context == NULL ) |
|
44 return( CKR_HOST_MEMORY ); |
|
45 |
|
46 MD2_Begin( md2_context ); |
|
47 |
|
48 MD2_Update( md2_context, known_hash_message, |
|
49 FIPS_KNOWN_HASH_MESSAGE_LENGTH ); |
|
50 |
|
51 MD2_End( md2_context, md2_computed_digest, &md2_bytes_hashed, MD2_LENGTH ); |
|
52 |
|
53 MD2_DestroyContext( md2_context , PR_TRUE ); |
|
54 |
|
55 if( ( md2_bytes_hashed != MD2_LENGTH ) || |
|
56 ( PORT_Memcmp( md2_computed_digest, md2_known_digest, |
|
57 MD2_LENGTH ) != 0 ) ) |
|
58 return( CKR_DEVICE_ERROR ); |
|
59 |
|
60 return( CKR_OK ); |
|
61 } |
|
62 |
|
63 |
|
64 |
|
65 static CK_RV |
|
66 freebl_fips_MD5_PowerUpSelfTest( void ) |
|
67 { |
|
68 /* MD5 Known Digest Message (128-bits). */ |
|
69 static const PRUint8 md5_known_digest[] = { |
|
70 0x25,0xc8,0xc0,0x10,0xc5,0x6e,0x68,0x28, |
|
71 0x28,0xa4,0xa5,0xd2,0x98,0x9a,0xea,0x2d}; |
|
72 |
|
73 /* MD5 variables. */ |
|
74 PRUint8 md5_computed_digest[MD5_LENGTH]; |
|
75 SECStatus md5_status; |
|
76 |
|
77 |
|
78 /***********************************************/ |
|
79 /* MD5 Single-Round Known Answer Hashing Test. */ |
|
80 /***********************************************/ |
|
81 |
|
82 md5_status = MD5_HashBuf( md5_computed_digest, known_hash_message, |
|
83 FIPS_KNOWN_HASH_MESSAGE_LENGTH ); |
|
84 |
|
85 if( ( md5_status != SECSuccess ) || |
|
86 ( PORT_Memcmp( md5_computed_digest, md5_known_digest, |
|
87 MD5_LENGTH ) != 0 ) ) |
|
88 return( CKR_DEVICE_ERROR ); |
|
89 |
|
90 return( CKR_OK ); |
|
91 } |
|
92 |
|
93 static CK_RV |
|
94 freebl_fips_SHA_PowerUpSelfTest( void ) |
|
95 { |
|
96 /* SHA-1 Known Digest Message (160-bits). */ |
|
97 static const PRUint8 sha1_known_digest[] = { |
|
98 0x0a,0x6d,0x07,0xba,0x1e,0xbd,0x8a,0x1b, |
|
99 0x72,0xf6,0xc7,0x22,0xf1,0x27,0x9f,0xf0, |
|
100 0xe0,0x68,0x47,0x7a}; |
|
101 |
|
102 /* SHA-224 Known Digest Message (224-bits). */ |
|
103 static const PRUint8 sha224_known_digest[] = { |
|
104 0x89,0x5e,0x7f,0xfd,0x0e,0xd8,0x35,0x6f, |
|
105 0x64,0x6d,0xf2,0xde,0x5e,0xed,0xa6,0x7f, |
|
106 0x29,0xd1,0x12,0x73,0x42,0x84,0x95,0x4f, |
|
107 0x8e,0x08,0xe5,0xcb}; |
|
108 |
|
109 /* SHA-256 Known Digest Message (256-bits). */ |
|
110 static const PRUint8 sha256_known_digest[] = { |
|
111 0x38,0xa9,0xc1,0xf0,0x35,0xf6,0x5d,0x61, |
|
112 0x11,0xd4,0x0b,0xdc,0xce,0x35,0x14,0x8d, |
|
113 0xf2,0xdd,0xaf,0xaf,0xcf,0xb7,0x87,0xe9, |
|
114 0x96,0xa5,0xd2,0x83,0x62,0x46,0x56,0x79}; |
|
115 |
|
116 /* SHA-384 Known Digest Message (384-bits). */ |
|
117 static const PRUint8 sha384_known_digest[] = { |
|
118 0x11,0xfe,0x1c,0x00,0x89,0x48,0xde,0xb3, |
|
119 0x99,0xee,0x1c,0x18,0xb4,0x10,0xfb,0xfe, |
|
120 0xe3,0xa8,0x2c,0xf3,0x04,0xb0,0x2f,0xc8, |
|
121 0xa3,0xc4,0x5e,0xea,0x7e,0x60,0x48,0x7b, |
|
122 0xce,0x2c,0x62,0xf7,0xbc,0xa7,0xe8,0xa3, |
|
123 0xcf,0x24,0xce,0x9c,0xe2,0x8b,0x09,0x72}; |
|
124 |
|
125 /* SHA-512 Known Digest Message (512-bits). */ |
|
126 static const PRUint8 sha512_known_digest[] = { |
|
127 0xc8,0xb3,0x27,0xf9,0x0b,0x24,0xc8,0xbf, |
|
128 0x4c,0xba,0x33,0x54,0xf2,0x31,0xbf,0xdb, |
|
129 0xab,0xfd,0xb3,0x15,0xd7,0xfa,0x48,0x99, |
|
130 0x07,0x60,0x0f,0x57,0x41,0x1a,0xdd,0x28, |
|
131 0x12,0x55,0x25,0xac,0xba,0x3a,0x99,0x12, |
|
132 0x2c,0x7a,0x8f,0x75,0x3a,0xe1,0x06,0x6f, |
|
133 0x30,0x31,0xc9,0x33,0xc6,0x1b,0x90,0x1a, |
|
134 0x6c,0x98,0x9a,0x87,0xd0,0xb2,0xf8,0x07}; |
|
135 |
|
136 /* SHA-X variables. */ |
|
137 PRUint8 sha_computed_digest[HASH_LENGTH_MAX]; |
|
138 SECStatus sha_status; |
|
139 |
|
140 /*************************************************/ |
|
141 /* SHA-1 Single-Round Known Answer Hashing Test. */ |
|
142 /*************************************************/ |
|
143 |
|
144 sha_status = SHA1_HashBuf( sha_computed_digest, known_hash_message, |
|
145 FIPS_KNOWN_HASH_MESSAGE_LENGTH ); |
|
146 |
|
147 if( ( sha_status != SECSuccess ) || |
|
148 ( PORT_Memcmp( sha_computed_digest, sha1_known_digest, |
|
149 SHA1_LENGTH ) != 0 ) ) |
|
150 return( CKR_DEVICE_ERROR ); |
|
151 |
|
152 /***************************************************/ |
|
153 /* SHA-224 Single-Round Known Answer Hashing Test. */ |
|
154 /***************************************************/ |
|
155 |
|
156 sha_status = SHA224_HashBuf( sha_computed_digest, known_hash_message, |
|
157 FIPS_KNOWN_HASH_MESSAGE_LENGTH ); |
|
158 |
|
159 if( ( sha_status != SECSuccess ) || |
|
160 ( PORT_Memcmp( sha_computed_digest, sha224_known_digest, |
|
161 SHA224_LENGTH ) != 0 ) ) |
|
162 return( CKR_DEVICE_ERROR ); |
|
163 |
|
164 /***************************************************/ |
|
165 /* SHA-256 Single-Round Known Answer Hashing Test. */ |
|
166 /***************************************************/ |
|
167 |
|
168 sha_status = SHA256_HashBuf( sha_computed_digest, known_hash_message, |
|
169 FIPS_KNOWN_HASH_MESSAGE_LENGTH ); |
|
170 |
|
171 if( ( sha_status != SECSuccess ) || |
|
172 ( PORT_Memcmp( sha_computed_digest, sha256_known_digest, |
|
173 SHA256_LENGTH ) != 0 ) ) |
|
174 return( CKR_DEVICE_ERROR ); |
|
175 |
|
176 /***************************************************/ |
|
177 /* SHA-384 Single-Round Known Answer Hashing Test. */ |
|
178 /***************************************************/ |
|
179 |
|
180 sha_status = SHA384_HashBuf( sha_computed_digest, known_hash_message, |
|
181 FIPS_KNOWN_HASH_MESSAGE_LENGTH ); |
|
182 |
|
183 if( ( sha_status != SECSuccess ) || |
|
184 ( PORT_Memcmp( sha_computed_digest, sha384_known_digest, |
|
185 SHA384_LENGTH ) != 0 ) ) |
|
186 return( CKR_DEVICE_ERROR ); |
|
187 |
|
188 /***************************************************/ |
|
189 /* SHA-512 Single-Round Known Answer Hashing Test. */ |
|
190 /***************************************************/ |
|
191 |
|
192 sha_status = SHA512_HashBuf( sha_computed_digest, known_hash_message, |
|
193 FIPS_KNOWN_HASH_MESSAGE_LENGTH ); |
|
194 |
|
195 if( ( sha_status != SECSuccess ) || |
|
196 ( PORT_Memcmp( sha_computed_digest, sha512_known_digest, |
|
197 SHA512_LENGTH ) != 0 ) ) |
|
198 return( CKR_DEVICE_ERROR ); |
|
199 |
|
200 return( CKR_OK ); |
|
201 } |
|
202 |
|
203 |
|
204 static CK_RV |
|
205 freebl_fipsSoftwareIntegrityTest(void) |
|
206 { |
|
207 CK_RV crv = CKR_OK; |
|
208 |
|
209 /* make sure that our check file signatures are OK */ |
|
210 if (!BLAPI_VerifySelf(SHLIB_PREFIX"freebl"SHLIB_VERSION"."SHLIB_SUFFIX)) { |
|
211 crv = CKR_DEVICE_ERROR; /* better error code? checksum error? */ |
|
212 } |
|
213 return crv; |
|
214 } |
|
215 |
|
216 CK_RV |
|
217 freebl_fipsPowerUpSelfTest( void ) |
|
218 { |
|
219 CK_RV rv; |
|
220 |
|
221 /* MD2 Power-Up SelfTest(s). */ |
|
222 rv = freebl_fips_MD2_PowerUpSelfTest(); |
|
223 |
|
224 if( rv != CKR_OK ) |
|
225 return rv; |
|
226 |
|
227 /* MD5 Power-Up SelfTest(s). */ |
|
228 rv = freebl_fips_MD5_PowerUpSelfTest(); |
|
229 |
|
230 if( rv != CKR_OK ) |
|
231 return rv; |
|
232 |
|
233 /* SHA-X Power-Up SelfTest(s). */ |
|
234 rv = freebl_fips_SHA_PowerUpSelfTest(); |
|
235 |
|
236 if( rv != CKR_OK ) |
|
237 return rv; |
|
238 |
|
239 /* Software/Firmware Integrity Test. */ |
|
240 rv = freebl_fipsSoftwareIntegrityTest(); |
|
241 |
|
242 if( rv != CKR_OK ) |
|
243 return rv; |
|
244 |
|
245 /* Passed Power-Up SelfTest(s). */ |
|
246 return( CKR_OK ); |
|
247 } |
|
248 |
|
249 struct NSSLOWInitContextStr { |
|
250 int count; |
|
251 }; |
|
252 |
|
253 struct NSSLOWHASHContextStr { |
|
254 const SECHashObject *hashObj; |
|
255 void *hashCtxt; |
|
256 |
|
257 }; |
|
258 |
|
259 static int nsslow_GetFIPSEnabled(void) { |
|
260 #ifdef LINUX |
|
261 FILE *f; |
|
262 char d; |
|
263 size_t size; |
|
264 |
|
265 f = fopen("/proc/sys/crypto/fips_enabled", "r"); |
|
266 if (!f) |
|
267 return 0; |
|
268 |
|
269 size = fread(&d, 1, 1, f); |
|
270 fclose(f); |
|
271 if (size != 1) |
|
272 return 0; |
|
273 if (d != '1') |
|
274 return 0; |
|
275 #endif |
|
276 return 1; |
|
277 } |
|
278 |
|
279 |
|
280 static int post = 0; |
|
281 static int post_failed = 0; |
|
282 |
|
283 static NSSLOWInitContext dummyContext = { 0 }; |
|
284 |
|
285 NSSLOWInitContext * |
|
286 NSSLOW_Init(void) |
|
287 { |
|
288 SECStatus rv; |
|
289 CK_RV crv; |
|
290 #ifdef FREEBL_NO_DEPEND |
|
291 PRBool nsprAvailable = PR_FALSE; |
|
292 |
|
293 |
|
294 rv = FREEBL_InitStubs(); |
|
295 nsprAvailable = (rv == SECSuccess ) ? PR_TRUE : PR_FALSE; |
|
296 #endif |
|
297 |
|
298 if (post_failed) { |
|
299 return NULL; |
|
300 } |
|
301 |
|
302 |
|
303 if (!post && nsslow_GetFIPSEnabled()) { |
|
304 crv = freebl_fipsPowerUpSelfTest(); |
|
305 if (crv != CKR_OK) { |
|
306 post_failed = 1; |
|
307 return NULL; |
|
308 } |
|
309 } |
|
310 post = 1; |
|
311 |
|
312 |
|
313 return &dummyContext; |
|
314 } |
|
315 |
|
316 void |
|
317 NSSLOW_Shutdown(NSSLOWInitContext *context) |
|
318 { |
|
319 PORT_Assert(context == &dummyContext); |
|
320 return; |
|
321 } |
|
322 |
|
323 void |
|
324 NSSLOW_Reset(NSSLOWInitContext *context) |
|
325 { |
|
326 PORT_Assert(context == &dummyContext); |
|
327 post_failed = 0; |
|
328 post = 0; |
|
329 return; |
|
330 } |
|
331 |
|
332 NSSLOWHASHContext * |
|
333 NSSLOWHASH_NewContext(NSSLOWInitContext *initContext, |
|
334 HASH_HashType hashType) |
|
335 { |
|
336 NSSLOWHASHContext *context; |
|
337 |
|
338 if (post_failed) { |
|
339 PORT_SetError(SEC_ERROR_PKCS11_DEVICE_ERROR); |
|
340 return NULL; |
|
341 } |
|
342 |
|
343 if (initContext != &dummyContext) { |
|
344 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
345 return (NULL); |
|
346 } |
|
347 |
|
348 context = PORT_ZNew(NSSLOWHASHContext); |
|
349 if (!context) { |
|
350 return NULL; |
|
351 } |
|
352 context->hashObj = HASH_GetRawHashObject(hashType); |
|
353 if (!context->hashObj) { |
|
354 PORT_Free(context); |
|
355 return NULL; |
|
356 } |
|
357 context->hashCtxt = context->hashObj->create(); |
|
358 if (!context->hashCtxt) { |
|
359 PORT_Free(context); |
|
360 return NULL; |
|
361 } |
|
362 |
|
363 return context; |
|
364 } |
|
365 |
|
366 void |
|
367 NSSLOWHASH_Begin(NSSLOWHASHContext *context) |
|
368 { |
|
369 return context->hashObj->begin(context->hashCtxt); |
|
370 } |
|
371 |
|
372 void |
|
373 NSSLOWHASH_Update(NSSLOWHASHContext *context, const unsigned char *buf, |
|
374 unsigned int len) |
|
375 { |
|
376 return context->hashObj->update(context->hashCtxt, buf, len); |
|
377 } |
|
378 |
|
379 void |
|
380 NSSLOWHASH_End(NSSLOWHASHContext *context, unsigned char *buf, |
|
381 unsigned int *ret, unsigned int len) |
|
382 { |
|
383 return context->hashObj->end(context->hashCtxt, buf, ret, len); |
|
384 } |
|
385 |
|
386 void |
|
387 NSSLOWHASH_Destroy(NSSLOWHASHContext *context) |
|
388 { |
|
389 context->hashObj->destroy(context->hashCtxt, PR_TRUE); |
|
390 PORT_Free(context); |
|
391 } |
|
392 |
|
393 unsigned int |
|
394 NSSLOWHASH_Length(NSSLOWHASHContext *context) |
|
395 { |
|
396 return context->hashObj->length; |
|
397 } |