Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(603)

Side by Side Diff: mozilla/security/nss/lib/softoken/rsawrapr.c

Issue 12207073: Update to NSS 3.14.3 Beta 1 for the TLS CBC constant-time (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Remove unrelated WIN64 changes from nss.gyp Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * PKCS#1 encoding and decoding functions. 2 * PKCS#1 encoding and decoding functions.
3 * This file is believed to contain no code licensed from other parties. 3 * This file is believed to contain no code licensed from other parties.
4 * 4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public 5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 /* $Id: rsawrapr.c,v 1.21 2012/06/26 22:27:31 rrelyea%redhat.com Exp $ */ 8 /* $Id: rsawrapr.c,v 1.22 2013/02/05 02:19:52 ryan.sleevi%gmail.com Exp $ */
9 9
10 #include "blapi.h" 10 #include "blapi.h"
11 #include "softoken.h" 11 #include "softoken.h"
12 12
13 #include "lowkeyi.h" 13 #include "lowkeyi.h"
14 #include "secerr.h" 14 #include "secerr.h"
15 15
16 #define RSA_BLOCK_MIN_PAD_LEN 8 16 #define RSA_BLOCK_MIN_PAD_LEN 8
17 #define RSA_BLOCK_FIRST_OCTET 0x00 17 #define RSA_BLOCK_FIRST_OCTET 0x00
18 #define RSA_BLOCK_PRIVATE0_PAD_OCTET 0x00 18 #define RSA_BLOCK_PRIVATE0_PAD_OCTET 0x00
19 #define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff 19 #define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff
20 #define RSA_BLOCK_AFTER_PAD_OCTET 0x00 20 #define RSA_BLOCK_AFTER_PAD_OCTET 0x00
21 21
22 #define OAEP_SALT_LEN 8
23 #define OAEP_PAD_LEN 8
24 #define OAEP_PAD_OCTET 0x00
25
26 #define FLAT_BUFSIZE 512 /* bytes to hold flattened SHA1Context. */
27
28 /* Needed for RSA-PSS functions */ 22 /* Needed for RSA-PSS functions */
29 static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 23 static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
30 24
31 static SHA1Context * 25 /* Constant time comparison of a single byte.
32 SHA1_CloneContext(SHA1Context *original) 26 * Returns 1 iff a == b, otherwise returns 0.
27 * Note: For ranges of bytes, use constantTimeCompare.
28 */
29 static unsigned char constantTimeEQ8(unsigned char a, unsigned char b) {
30 unsigned char c = ~(a - b | b - a);
31 c >>= 7;
32 return c;
33 }
34
35 /* Constant time comparison of a range of bytes.
36 * Returns 1 iff len bytes of a are identical to len bytes of b, otherwise
37 * returns 0.
38 */
39 static unsigned char constantTimeCompare(const unsigned char *a,
40 const unsigned char *b,
41 unsigned int len) {
42 unsigned char tmp = 0;
43 unsigned int i;
44 for (i = 0; i < len; ++i, ++a, ++b)
45 tmp |= *a ^ *b;
46 return constantTimeEQ8(0x00, tmp);
47 }
48
49 /* Constant time conditional.
50 * Returns a if c is 1, or b if c is 0. The result is undefined if c is
51 * not 0 or 1.
52 */
53 static unsigned int constantTimeCondition(unsigned int c,
54 unsigned int a,
55 unsigned int b)
33 { 56 {
34 SHA1Context * clone» = NULL; 57 return (~(c - 1) & a) | ((c - 1) & b);
35 unsigned char *pBuf;
36 int sha1ContextSize = SHA1_FlattenSize(original);
37 SECStatus frv;
38 unsigned char buf[FLAT_BUFSIZE];
39
40 PORT_Assert(sizeof buf >= sha1ContextSize);
41 if (sizeof buf >= sha1ContextSize) {
42 » pBuf = buf;
43 } else {
44 pBuf = PORT_Alloc(sha1ContextSize);
45 » if (!pBuf)
46 » goto done;
47 }
48
49 frv = SHA1_Flatten(original, pBuf);
50 if (frv == SECSuccess) {
51 » clone = SHA1_Resurrect(pBuf, NULL);
52 » memset(pBuf, 0, sha1ContextSize);
53 }
54 done:
55 if (pBuf != buf)
56 » PORT_Free(pBuf);
57 return clone;
58 } 58 }
59 59
60 /* 60 /*
61 * Modify data by XORing it with a special hash of salt.
62 */
63 static SECStatus
64 oaep_xor_with_h1(unsigned char *data, unsigned int datalen,
65 unsigned char *salt, unsigned int saltlen)
66 {
67 SHA1Context *sha1cx;
68 unsigned char *dp, *dataend;
69 unsigned char end_octet;
70
71 sha1cx = SHA1_NewContext();
72 if (sha1cx == NULL) {
73 return SECFailure;
74 }
75
76 /*
77 * Get a hash of salt started; we will use it several times,
78 * adding in a different end octet (x00, x01, x02, ...).
79 */
80 SHA1_Begin (sha1cx);
81 SHA1_Update (sha1cx, salt, saltlen);
82 end_octet = 0;
83
84 dp = data;
85 dataend = data + datalen;
86
87 while (dp < dataend) {
88 SHA1Context *sha1cx_h1;
89 unsigned int sha1len, sha1off;
90 unsigned char sha1[SHA1_LENGTH];
91
92 /*
93 * Create hash of (salt || end_octet)
94 */
95 sha1cx_h1 = SHA1_CloneContext (sha1cx);
96 SHA1_Update (sha1cx_h1, &end_octet, 1);
97 SHA1_End (sha1cx_h1, sha1, &sha1len, sizeof(sha1));
98 SHA1_DestroyContext (sha1cx_h1, PR_TRUE);
99 PORT_Assert (sha1len == SHA1_LENGTH);
100
101 /*
102 * XOR that hash with the data.
103 * When we have fewer than SHA1_LENGTH octets of data
104 * left to xor, use just the low-order ones of the hash.
105 */
106 sha1off = 0;
107 if ((dataend - dp) < SHA1_LENGTH)
108 sha1off = SHA1_LENGTH - (dataend - dp);
109 while (sha1off < SHA1_LENGTH)
110 *dp++ ^= sha1[sha1off++];
111
112 /*
113 * Bump for next hash chunk.
114 */
115 end_octet++;
116 }
117
118 SHA1_DestroyContext (sha1cx, PR_TRUE);
119 return SECSuccess;
120 }
121
122 /*
123 * Modify salt by XORing it with a special hash of data.
124 */
125 static SECStatus
126 oaep_xor_with_h2(unsigned char *salt, unsigned int saltlen,
127 unsigned char *data, unsigned int datalen)
128 {
129 unsigned char sha1[SHA1_LENGTH];
130 unsigned char *psalt, *psha1, *saltend;
131 SECStatus rv;
132
133 /*
134 * Create a hash of data.
135 */
136 rv = SHA1_HashBuf (sha1, data, datalen);
137 if (rv != SECSuccess) {
138 return rv;
139 }
140
141 /*
142 * XOR the low-order octets of that hash with salt.
143 */
144 PORT_Assert (saltlen <= SHA1_LENGTH);
145 saltend = salt + saltlen;
146 psalt = salt;
147 psha1 = sha1 + SHA1_LENGTH - saltlen;
148 while (psalt < saltend) {
149 *psalt++ ^= *psha1++;
150 }
151
152 return SECSuccess;
153 }
154
155 /*
156 * Format one block of data for public/private key encryption using 61 * Format one block of data for public/private key encryption using
157 * the rules defined in PKCS #1. 62 * the rules defined in PKCS #1.
158 */ 63 */
159 static unsigned char * 64 static unsigned char *
160 rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, 65 rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType,
161 SECItem *data) 66 SECItem *data)
162 { 67 {
163 unsigned char *block; 68 unsigned char *block;
164 unsigned char *bp; 69 unsigned char *bp;
165 int padLen; 70 int padLen;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 if (rv != SECSuccess) { 163 if (rv != SECSuccess) {
259 sftk_fatalError = PR_TRUE; 164 sftk_fatalError = PR_TRUE;
260 PORT_Free (block); 165 PORT_Free (block);
261 return NULL; 166 return NULL;
262 } 167 }
263 bp += padLen; 168 bp += padLen;
264 *bp++ = RSA_BLOCK_AFTER_PAD_OCTET; 169 *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
265 PORT_Memcpy (bp, data->data, data->len); 170 PORT_Memcpy (bp, data->data, data->len);
266 break; 171 break;
267 172
268 /*
269 * Blocks intended for public-key operation, using
270 * Optimal Asymmetric Encryption Padding (OAEP).
271 */
272 case RSA_BlockOAEP:
273 /*
274 * 0x00 || BT || Modified2(Salt) || Modified1(PaddedData)
275 * 1 1 OAEP_SALT_LEN OAEP_PAD_LEN + data->len [+ N]
276 *
277 * where:
278 * PaddedData is "Pad1 || ActualData [|| Pad2]"
279 * Salt is random data.
280 * Pad1 is all zeros.
281 * Pad2, if present, is random data.
282 * (The "modified" fields are all the same length as the original
283 * unmodified values; they are just xor'd with other values.)
284 *
285 * Modified1 is an XOR of PaddedData with a special octet
286 * string constructed of iterated hashing of Salt (see below).
287 * Modified2 is an XOR of Salt with the low-order octets of
288 * the hash of Modified1 (see farther below ;-).
289 *
290 * Whew!
291 */
292
293
294 /*
295 * Salt
296 */
297 rv = RNG_GenerateGlobalRandomBytes(bp, OAEP_SALT_LEN);
298 if (rv != SECSuccess) {
299 sftk_fatalError = PR_TRUE;
300 PORT_Free (block);
301 return NULL;
302 }
303 bp += OAEP_SALT_LEN;
304
305 /*
306 * Pad1
307 */
308 PORT_Memset (bp, OAEP_PAD_OCTET, OAEP_PAD_LEN);
309 bp += OAEP_PAD_LEN;
310
311 /*
312 * Data
313 */
314 PORT_Memcpy (bp, data->data, data->len);
315 bp += data->len;
316
317 /*
318 * Pad2
319 */
320 if (bp < (block + modulusLen)) {
321 rv = RNG_GenerateGlobalRandomBytes(bp, block - bp + modulusLen);
322 if (rv != SECSuccess) {
323 sftk_fatalError = PR_TRUE;
324 PORT_Free (block);
325 return NULL;
326 }
327 }
328
329 /*
330 * Now we have the following:
331 * 0x00 || BT || Salt || PaddedData
332 * (From this point on, "Pad1 || Data [|| Pad2]" is treated
333 * as the one entity PaddedData.)
334 *
335 * We need to turn PaddedData into Modified1.
336 */
337 if (oaep_xor_with_h1(block + 2 + OAEP_SALT_LEN,
338 modulusLen - 2 - OAEP_SALT_LEN,
339 block + 2, OAEP_SALT_LEN) != SECSuccess) {
340 PORT_Free (block);
341 return NULL;
342 }
343
344 /*
345 * Now we have:
346 * 0x00 || BT || Salt || Modified1(PaddedData)
347 *
348 * The remaining task is to turn Salt into Modified2.
349 */
350 if (oaep_xor_with_h2(block + 2, OAEP_SALT_LEN,
351 block + 2 + OAEP_SALT_LEN,
352 modulusLen - 2 - OAEP_SALT_LEN) != SECSuccess) {
353 PORT_Free (block);
354 return NULL;
355 }
356
357 break;
358
359 default: 173 default:
360 PORT_Assert (0); 174 PORT_Assert (0);
361 PORT_Free (block); 175 PORT_Free (block);
362 return NULL; 176 return NULL;
363 } 177 }
364 178
365 return block; 179 return block;
366 } 180 }
367 181
368 static SECStatus 182 static SECStatus
(...skipping 27 matching lines...) Expand all
396 210
397 result->data = rsa_FormatOneBlock(modulusLen, blockType, data); 211 result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
398 if (result->data == NULL) { 212 if (result->data == NULL) {
399 result->len = 0; 213 result->len = 0;
400 return SECFailure; 214 return SECFailure;
401 } 215 }
402 result->len = modulusLen; 216 result->len = modulusLen;
403 217
404 break; 218 break;
405 219
406 case RSA_BlockOAEP:
407 /*
408 * 0x00 || BT || M1(Salt) || M2(Pad1||ActualData[||Pad2])
409 *
410 * The "2" below is the first octet + the second octet.
411 * (The other fields do not contain the clear values, but are
412 * the same length as the clear values.)
413 */
414 PORT_Assert (data->len <= (modulusLen - (2 + OAEP_SALT_LEN
415 + OAEP_PAD_LEN)));
416
417 result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
418 if (result->data == NULL) {
419 result->len = 0;
420 return SECFailure;
421 }
422 result->len = modulusLen;
423
424 break;
425
426 case RSA_BlockRaw: 220 case RSA_BlockRaw:
427 /* 221 /*
428 * Pad || ActualData 222 * Pad || ActualData
429 * Pad is zeros. The application is responsible for recovering 223 * Pad is zeros. The application is responsible for recovering
430 * the actual data. 224 * the actual data.
431 */ 225 */
432 if (data->len > modulusLen ) { 226 if (data->len > modulusLen ) {
433 return SECFailure; 227 return SECFailure;
434 } 228 }
435 result->data = (unsigned char*)PORT_ZAlloc(modulusLen); 229 result->data = (unsigned char*)PORT_ZAlloc(modulusLen);
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length); 746 PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length);
953 PORT_Free(temp); 747 PORT_Free(temp);
954 } 748 }
955 } 749 }
956 (*hash->destroy)(hashContext, PR_TRUE); 750 (*hash->destroy)(hashContext, PR_TRUE);
957 751
958 return SECSuccess; 752 return SECSuccess;
959 } 753 }
960 754
961 /* 755 /*
756 * Decodes an EME-OAEP encoded block, validating the encoding in constant
757 * time.
758 * Described in RFC 3447, section 7.1.2.
759 * input contains the encoded block, after decryption.
760 * label is the optional value L that was associated with the message.
761 * On success, the original message and message length will be stored in
762 * output and outputLen.
763 */
764 static SECStatus
765 eme_oaep_decode(unsigned char *output, unsigned int *outputLen,
766 unsigned int maxOutputLen,
767 const unsigned char *input, unsigned int inputLen,
768 HASH_HashType hashAlg, HASH_HashType maskHashAlg,
769 const unsigned char *label, unsigned int labelLen)
770 {
771 const SECHashObject *hash;
772 void *hashContext;
773 SECStatus rv = SECFailure;
774 unsigned char labelHash[HASH_LENGTH_MAX];
775 unsigned int i, maskLen, paddingOffset;
776 unsigned char *mask = NULL, *tmpOutput = NULL;
777 unsigned char isGood, foundPaddingEnd;
778
779 hash = HASH_GetRawHashObject(hashAlg);
780
781 /* 1.c */
782 if (inputLen < (hash->length * 2) + 2) {
783 PORT_SetError(SEC_ERROR_INPUT_LEN);
784 return SECFailure;
785 }
786
787 /* Step 3.a - Generate lHash */
788 hashContext = (*hash->create)();
789 if (hashContext == NULL) {
790 PORT_SetError(SEC_ERROR_NO_MEMORY);
791 return SECFailure;
792 }
793 (*hash->begin)(hashContext);
794 if (labelLen > 0)
795 (*hash->update)(hashContext, label, labelLen);
796 (*hash->end)(hashContext, labelHash, &i, sizeof(labelHash));
797 (*hash->destroy)(hashContext, PR_TRUE);
798
799 tmpOutput = (unsigned char*)PORT_Alloc(inputLen);
800 if (tmpOutput == NULL) {
801 PORT_SetError(SEC_ERROR_NO_MEMORY);
802 goto done;
803 }
804
805 maskLen = inputLen - hash->length - 1;
806 mask = (unsigned char*)PORT_Alloc(maskLen);
807 if (mask == NULL) {
808 PORT_SetError(SEC_ERROR_NO_MEMORY);
809 goto done;
810 }
811
812 PORT_Memcpy(tmpOutput, input, inputLen);
813
814 /* 3.c - Generate seedMask */
815 MGF1(maskHashAlg, mask, hash->length, &tmpOutput[1 + hash->length],
816 inputLen - hash->length - 1);
817 /* 3.d - Unmask seed */
818 for (i = 0; i < hash->length; ++i)
819 tmpOutput[1 + i] ^= mask[i];
820
821 /* 3.e - Generate dbMask */
822 MGF1(maskHashAlg, mask, maskLen, &tmpOutput[1], hash->length);
823 /* 3.f - Unmask DB */
824 for (i = 0; i < maskLen; ++i)
825 tmpOutput[1 + hash->length + i] ^= mask[i];
826
827 /* 3.g - Compare Y, lHash, and PS in constant time
828 * Warning: This code is timing dependent and must not disclose which of
829 * these were invalid.
830 */
831 paddingOffset = 0;
832 isGood = 1;
833 foundPaddingEnd = 0;
834
835 /* Compare Y */
836 isGood &= constantTimeEQ8(0x00, tmpOutput[0]);
837
838 /* Compare lHash and lHash' */
839 isGood &= constantTimeCompare(&labelHash[0],
840 &tmpOutput[1 + hash->length],
841 hash->length);
842
843 /* Compare that the padding is zero or more zero octets, followed by a
844 * 0x01 octet */
845 for (i = 1 + (hash->length * 2); i < inputLen; ++i) {
846 unsigned char isZero = constantTimeEQ8(0x00, tmpOutput[i]);
847 unsigned char isOne = constantTimeEQ8(0x01, tmpOutput[i]);
848 /* non-constant time equivalent:
849 * if (tmpOutput[i] == 0x01 && !foundPaddingEnd)
850 * paddingOffset = i;
851 */
852 paddingOffset = constantTimeCondition(isOne & ~foundPaddingEnd, i,
853 paddingOffset);
854 /* non-constant time equivalent:
855 * if (tmpOutput[i] == 0x01)
856 * foundPaddingEnd = true;
857 *
858 * Note: This may yield false positives, as it will be set whenever
859 * a 0x01 byte is encountered. If there was bad padding (eg:
860 * 0x03 0x02 0x01), foundPaddingEnd will still be set to true, and
861 * paddingOffset will still be set to 2.
862 */
863 foundPaddingEnd = constantTimeCondition(isOne, 1, foundPaddingEnd);
864 /* non-constant time equivalent:
865 * if (tmpOutput[i] != 0x00 && tmpOutput[i] != 0x01 &&
866 * !foundPaddingEnd) {
867 * isGood = false;
868 * }
869 *
870 * Note: This may yield false positives, as a message (and padding)
871 * that is entirely zeros will result in isGood still being true. Thus
872 * it's necessary to check foundPaddingEnd is positive below.
873 */
874 isGood = constantTimeCondition(~foundPaddingEnd & ~isZero, 0, isGood);
875 }
876
877 /* While both isGood and foundPaddingEnd may have false positives, they
878 * cannot BOTH have false positives. If both are not true, then an invalid
879 * message was received. Note, this comparison must still be done in constan t
880 * time so as not to leak either condition.
881 */
882 if (!(isGood & foundPaddingEnd)) {
883 PORT_SetError(SEC_ERROR_BAD_DATA);
884 goto done;
885 }
886
887 /* End timing dependent code */
888
889 ++paddingOffset; /* Skip the 0x01 following the end of PS */
890
891 *outputLen = inputLen - paddingOffset;
892 if (*outputLen > maxOutputLen) {
893 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
894 goto done;
895 }
896
897 if (*outputLen)
898 PORT_Memcpy(output, &tmpOutput[paddingOffset], *outputLen);
899 rv = SECSuccess;
900
901 done:
902 if (mask)
903 PORT_ZFree(mask, maskLen);
904 if (tmpOutput)
905 PORT_ZFree(tmpOutput, inputLen);
906 return rv;
907 }
908
909 /*
910 * Generate an EME-OAEP encoded block for encryption
911 * Described in RFC 3447, section 7.1.1
912 * We use input instead of M for the message to be encrypted
913 * label is the optional value L to be associated with the message.
914 */
915 static SECStatus
916 eme_oaep_encode(unsigned char *em, unsigned int emLen,
917 const unsigned char *input, unsigned int inputLen,
918 HASH_HashType hashAlg, HASH_HashType maskHashAlg,
919 const unsigned char *label, unsigned int labelLen)
920 {
921 const SECHashObject *hash;
922 void *hashContext;
923 SECStatus rv;
924 unsigned char *mask;
925 unsigned int reservedLen, dbMaskLen, i;
926
927 hash = HASH_GetRawHashObject(hashAlg);
928
929 /* Step 1.b */
930 reservedLen = (2 * hash->length) + 2;
931 if (emLen < reservedLen || inputLen > (emLen - reservedLen)) {
932 PORT_SetError(SEC_ERROR_INPUT_LEN);
933 return SECFailure;
934 }
935
936 /*
937 * From RFC 3447, Section 7.1
938 * +----------+---------+-------+
939 * DB = | lHash | PS | M |
940 * +----------+---------+-------+
941 * |
942 * +----------+ V
943 * | seed |--> MGF ---> xor
944 * +----------+ |
945 * | |
946 * +--+ V |
947 * |00| xor <----- MGF <-----|
948 * +--+ | |
949 * | | |
950 * V V V
951 * +--+----------+----------------------------+
952 * EM = |00|maskedSeed| maskedDB |
953 * +--+----------+----------------------------+
954 *
955 * We use mask to hold the result of the MGF functions, and all other
956 * values are generated in their final resting place.
957 */
958 *em = 0x00;
959
960 /* Step 2.a - Generate lHash */
961 hashContext = (*hash->create)();
962 if (hashContext == NULL) {
963 PORT_SetError(SEC_ERROR_NO_MEMORY);
964 return SECFailure;
965 }
966 (*hash->begin)(hashContext);
967 if (labelLen > 0)
968 (*hash->update)(hashContext, label, labelLen);
969 (*hash->end)(hashContext, &em[1 + hash->length], &i, hash->length);
970 (*hash->destroy)(hashContext, PR_TRUE);
971
972 /* Step 2.b - Generate PS */
973 if (emLen - reservedLen - inputLen > 0) {
974 PORT_Memset(em + 1 + (hash->length * 2), 0x00,
975 emLen - reservedLen - inputLen);
976 }
977
978 /* Step 2.c. - Generate DB
979 * DB = lHash || PS || 0x01 || M
980 * Note that PS and lHash have already been placed into em at their
981 * appropriate offsets. This just copies M into place
982 */
983 em[emLen - inputLen - 1] = 0x01;
984 if (inputLen)
985 PORT_Memcpy(em + emLen - inputLen, input, inputLen);
986
987 /* Step 2.d - Generate seed */
988 rv = RNG_GenerateGlobalRandomBytes(em + 1, hash->length);
989 if (rv != SECSuccess) {
990 return rv;
991 }
992
993 /* Step 2.e - Generate dbMask*/
994 dbMaskLen = emLen - hash->length - 1;
995 mask = (unsigned char*)PORT_Alloc(dbMaskLen);
996 if (mask == NULL) {
997 PORT_SetError(SEC_ERROR_NO_MEMORY);
998 return SECFailure;
999 }
1000 MGF1(maskHashAlg, mask, dbMaskLen, em + 1, hash->length);
1001 /* Step 2.f - Compute maskedDB*/
1002 for (i = 0; i < dbMaskLen; ++i)
1003 em[1 + hash->length + i] ^= mask[i];
1004
1005 /* Step 2.g - Generate seedMask */
1006 MGF1(maskHashAlg, mask, hash->length, &em[1 + hash->length], dbMaskLen);
1007 /* Step 2.h - Compute maskedSeed */
1008 for (i = 0; i < hash->length; ++i)
1009 em[1 + i] ^= mask[i];
1010
1011 PORT_ZFree(mask, dbMaskLen);
1012 return SECSuccess;
1013 }
1014
1015 /*
962 * Encode a RSA-PSS signature. 1016 * Encode a RSA-PSS signature.
963 * Described in RFC 3447, section 9.1.1. 1017 * Described in RFC 3447, section 9.1.1.
964 * We use mHash instead of M as input. 1018 * We use mHash instead of M as input.
965 * emBits from the RFC is just modBits - 1, see section 8.1.1. 1019 * emBits from the RFC is just modBits - 1, see section 8.1.1.
966 * We only support MGF1 as the MGF. 1020 * We only support MGF1 as the MGF.
967 * 1021 *
968 * NOTE: this code assumes modBits is a multiple of 8. 1022 * NOTE: this code assumes modBits is a multiple of 8.
969 */ 1023 */
970 static SECStatus 1024 static SECStatus
971 emsa_pss_encode(unsigned char *em, unsigned int emLen, 1025 emsa_pss_encode(unsigned char *em, unsigned int emLen,
(...skipping 29 matching lines...) Expand all
1001 return SECFailure; 1055 return SECFailure;
1002 } 1056 }
1003 (*hash->begin)(hash_context); 1057 (*hash->begin)(hash_context);
1004 (*hash->update)(hash_context, eightZeros, 8); 1058 (*hash->update)(hash_context, eightZeros, 8);
1005 (*hash->update)(hash_context, mHash, hash->length); 1059 (*hash->update)(hash_context, mHash, hash->length);
1006 (*hash->update)(hash_context, &em[dbMaskLen - sLen], sLen); 1060 (*hash->update)(hash_context, &em[dbMaskLen - sLen], sLen);
1007 (*hash->end)(hash_context, &em[dbMaskLen], &i, hash->length); 1061 (*hash->end)(hash_context, &em[dbMaskLen], &i, hash->length);
1008 (*hash->destroy)(hash_context, PR_TRUE); 1062 (*hash->destroy)(hash_context, PR_TRUE);
1009 1063
1010 /* Step 7 + 8 */ 1064 /* Step 7 + 8 */
1011 memset(em, 0, dbMaskLen - sLen - 1); 1065 PORT_Memset(em, 0, dbMaskLen - sLen - 1);
1012 em[dbMaskLen - sLen - 1] = 0x01; 1066 em[dbMaskLen - sLen - 1] = 0x01;
1013 1067
1014 /* Step 9 */ 1068 /* Step 9 */
1015 dbMask = (unsigned char *)PORT_Alloc(dbMaskLen); 1069 dbMask = (unsigned char *)PORT_Alloc(dbMaskLen);
1016 if (dbMask == NULL) { 1070 if (dbMask == NULL) {
1017 PORT_SetError(SEC_ERROR_NO_MEMORY); 1071 PORT_SetError(SEC_ERROR_NO_MEMORY);
1018 return SECFailure; 1072 return SECFailure;
1019 } 1073 }
1020 MGF1(maskHashAlg, dbMask, dbMaskLen, &em[dbMaskLen], hash->length); 1074 MGF1(maskHashAlg, dbMask, dbMaskLen, &em[dbMaskLen], hash->length);
1021 1075
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output, pss_encoded); 1298 rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output, pss_encoded);
1245 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { 1299 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
1246 sftk_fatalError = PR_TRUE; 1300 sftk_fatalError = PR_TRUE;
1247 } 1301 }
1248 *output_len = modulus_len; 1302 *output_len = modulus_len;
1249 1303
1250 done: 1304 done:
1251 PORT_Free(pss_encoded); 1305 PORT_Free(pss_encoded);
1252 return rv; 1306 return rv;
1253 } 1307 }
1308
1309 /* MGF1 is the only supported MGF. */
1310 SECStatus
1311 RSA_EncryptOAEP(CK_RSA_PKCS_OAEP_PARAMS *oaepParams,
1312 NSSLOWKEYPublicKey *key,
1313 unsigned char *output, unsigned int *outputLen,
1314 unsigned int maxOutputLen,
1315 const unsigned char *input, unsigned int inputLen)
1316 {
1317 SECStatus rv = SECFailure;
1318 unsigned int modulusLen = nsslowkey_PublicModulusLen(key);
1319 unsigned char *oaepEncoded = NULL;
1320 unsigned char *sourceData = NULL;
1321 unsigned int sourceDataLen = 0;
1322
1323 HASH_HashType hashAlg;
1324 HASH_HashType maskHashAlg;
1325
1326 if (maxOutputLen < modulusLen) {
1327 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1328 return SECFailure;
1329 }
1330 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
1331 if (key->keyType != NSSLOWKEYRSAKey) {
1332 PORT_SetError(SEC_ERROR_INVALID_KEY);
1333 return SECFailure;
1334 }
1335
1336 hashAlg = GetHashTypeFromMechanism(oaepParams->hashAlg);
1337 maskHashAlg = GetHashTypeFromMechanism(oaepParams->mgf);
1338 if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) {
1339 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1340 return SECFailure;
1341 }
1342
1343 /* The PKCS#11 source parameter is the "source" of the label parameter.
1344 * The only defined source is explicitly specified, in which case, the
1345 * label is an optional byte string in pSourceData. If ulSourceDataLen is
1346 * zero, then pSourceData MUST be NULL - otherwise, it must be non-NULL.
1347 */
1348 if (oaepParams->source != CKZ_DATA_SPECIFIED) {
1349 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1350 return SECFailure;
1351 }
1352 sourceData = (unsigned char*)oaepParams->pSourceData;
1353 sourceDataLen = oaepParams->ulSourceDataLen;
1354 if ((sourceDataLen == 0 && sourceData != NULL) ||
1355 (sourceDataLen > 0 && sourceData == NULL)) {
1356 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1357 return SECFailure;
1358 }
1359
1360 oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen);
1361 if (oaepEncoded == NULL) {
1362 PORT_SetError(SEC_ERROR_NO_MEMORY);
1363 return SECFailure;
1364 }
1365 rv = eme_oaep_encode(oaepEncoded, modulusLen, input, inputLen,
1366 hashAlg, maskHashAlg, sourceData, sourceDataLen);
1367 if (rv != SECSuccess)
1368 goto done;
1369
1370 rv = RSA_PublicKeyOp(&key->u.rsa, output, oaepEncoded);
1371 if (rv != SECSuccess)
1372 goto done;
1373 *outputLen = modulusLen;
1374
1375 done:
1376 PORT_Free(oaepEncoded);
1377 return rv;
1378 }
1379
1380 /* MGF1 is the only supported MGF. */
1381 SECStatus
1382 RSA_DecryptOAEP(CK_RSA_PKCS_OAEP_PARAMS *oaepParams,
1383 NSSLOWKEYPrivateKey *key,
1384 unsigned char *output, unsigned int *outputLen,
1385 unsigned int maxOutputLen,
1386 const unsigned char *input, unsigned int inputLen)
1387 {
1388 SECStatus rv = SECFailure;
1389 unsigned int modulusLen = nsslowkey_PrivateModulusLen(key);
1390 unsigned char *oaepEncoded = NULL;
1391 unsigned char *sourceData = NULL;
1392 unsigned int sourceDataLen = 0;
1393
1394 HASH_HashType hashAlg = GetHashTypeFromMechanism(oaepParams->hashAlg);
1395 HASH_HashType maskHashAlg = GetHashTypeFromMechanism(oaepParams->mgf);
1396
1397 if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) {
1398 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1399 return SECFailure;
1400 }
1401
1402 if (inputLen != modulusLen) {
1403 PORT_SetError(SEC_ERROR_INPUT_LEN);
1404 return SECFailure;
1405 }
1406 PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
1407 if (key->keyType != NSSLOWKEYRSAKey) {
1408 PORT_SetError(SEC_ERROR_INVALID_KEY);
1409 return SECFailure;
1410 }
1411
1412 /* The PKCS#11 source parameter is the "source" of the label parameter.
1413 * The only defined source is explicitly specified, in which case, the
1414 * label is an optional byte string in pSourceData. If ulSourceDataLen is
1415 * zero, then pSourceData MUST be NULL - otherwise, it must be non-NULL.
1416 */
1417 if (oaepParams->source != CKZ_DATA_SPECIFIED) {
1418 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1419 return SECFailure;
1420 }
1421 sourceData = (unsigned char*)oaepParams->pSourceData;
1422 sourceDataLen = oaepParams->ulSourceDataLen;
1423 if ((sourceDataLen == 0 && sourceData != NULL) ||
1424 (sourceDataLen > 0 && sourceData == NULL)) {
1425 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1426 return SECFailure;
1427 }
1428
1429 oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen);
1430 if (oaepEncoded == NULL) {
1431 PORT_SetError(SEC_ERROR_NO_MEMORY);
1432 return SECFailure;
1433 }
1434
1435 rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, oaepEncoded, input);
1436 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
1437 sftk_fatalError = PR_TRUE;
1438 goto done;
1439 }
1440
1441 rv = eme_oaep_decode(output, outputLen, maxOutputLen, oaepEncoded,
1442 modulusLen, hashAlg, maskHashAlg, sourceData,
1443 sourceDataLen);
1444
1445 done:
1446 if (oaepEncoded)
1447 PORT_ZFree(oaepEncoded, modulusLen);
1448 return rv;
1449 }
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/softoken/pkcs11i.h ('k') | mozilla/security/nss/lib/softoken/sftkhmac.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698