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

Side by Side Diff: nss/lib/cryptohi/secsign.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 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
« no previous file with comments | « nss/lib/cryptohi/seckey.c ('k') | nss/lib/cryptohi/secvfy.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Signature stuff.
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #include <stdio.h>
9 #include "cryptohi.h"
10 #include "sechash.h"
11 #include "secder.h"
12 #include "keyhi.h"
13 #include "secoid.h"
14 #include "secdig.h"
15 #include "pk11func.h"
16 #include "secerr.h"
17 #include "keyi.h"
18
19 struct SGNContextStr {
20 SECOidTag signalg;
21 SECOidTag hashalg;
22 void *hashcx;
23 const SECHashObject *hashobj;
24 SECKEYPrivateKey *key;
25 };
26
27 SGNContext *
28 SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
29 {
30 SGNContext *cx;
31 SECOidTag hashalg, signalg;
32 KeyType keyType;
33 SECStatus rv;
34
35 /* OK, map a PKCS #7 hash and encrypt algorithm into
36 * a standard hashing algorithm. Why did we pass in the whole
37 * PKCS #7 algTag if we were just going to change here you might
38 * ask. Well the answer is for some cards we may have to do the
39 * hashing on card. It may not support CKM_RSA_PKCS sign algorithm,
40 * it may just support CKM_SHA1_RSA_PKCS and/or CKM_MD5_RSA_PKCS.
41 */
42 /* we have a private key, not a public key, so don't pass it in */
43 rv = sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg);
44 if (rv != SECSuccess) {
45 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
46 return 0;
47 }
48 keyType = seckey_GetKeyType(signalg);
49
50 /* verify our key type */
51 if (key->keyType != keyType &&
52 !((key->keyType == dsaKey) && (keyType == fortezzaKey))) {
53 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
54 return 0;
55 }
56
57 cx = (SGNContext *)PORT_ZAlloc(sizeof(SGNContext));
58 if (cx) {
59 cx->hashalg = hashalg;
60 cx->signalg = signalg;
61 cx->key = key;
62 }
63 return cx;
64 }
65
66 void
67 SGN_DestroyContext(SGNContext *cx, PRBool freeit)
68 {
69 if (cx) {
70 if (cx->hashcx != NULL) {
71 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
72 cx->hashcx = NULL;
73 }
74 if (freeit) {
75 PORT_ZFree(cx, sizeof(SGNContext));
76 }
77 }
78 }
79
80 SECStatus
81 SGN_Begin(SGNContext *cx)
82 {
83 if (cx->hashcx != NULL) {
84 (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
85 cx->hashcx = NULL;
86 }
87
88 cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashalg);
89 if (!cx->hashobj)
90 return SECFailure; /* error code is already set */
91
92 cx->hashcx = (*cx->hashobj->create)();
93 if (cx->hashcx == NULL)
94 return SECFailure;
95
96 (*cx->hashobj->begin)(cx->hashcx);
97 return SECSuccess;
98 }
99
100 SECStatus
101 SGN_Update(SGNContext *cx, const unsigned char *input, unsigned int inputLen)
102 {
103 if (cx->hashcx == NULL) {
104 PORT_SetError(SEC_ERROR_INVALID_ARGS);
105 return SECFailure;
106 }
107 (*cx->hashobj->update)(cx->hashcx, input, inputLen);
108 return SECSuccess;
109 }
110
111 /* XXX Old template; want to expunge it eventually. */
112 static DERTemplate SECAlgorithmIDTemplate[] = {
113 { DER_SEQUENCE,
114 0, NULL, sizeof(SECAlgorithmID) },
115 { DER_OBJECT_ID,
116 offsetof(SECAlgorithmID, algorithm) },
117 { DER_OPTIONAL | DER_ANY,
118 offsetof(SECAlgorithmID, parameters) },
119 { 0 }
120 };
121
122 /*
123 * XXX OLD Template. Once all uses have been switched over to new one,
124 * remove this.
125 */
126 static DERTemplate SGNDigestInfoTemplate[] = {
127 { DER_SEQUENCE,
128 0, NULL, sizeof(SGNDigestInfo) },
129 { DER_INLINE,
130 offsetof(SGNDigestInfo, digestAlgorithm),
131 SECAlgorithmIDTemplate },
132 { DER_OCTET_STRING,
133 offsetof(SGNDigestInfo, digest) },
134 { 0 }
135 };
136
137 SECStatus
138 SGN_End(SGNContext *cx, SECItem *result)
139 {
140 unsigned char digest[HASH_LENGTH_MAX];
141 unsigned part1;
142 int signatureLen;
143 SECStatus rv;
144 SECItem digder, sigitem;
145 PLArenaPool *arena = 0;
146 SECKEYPrivateKey *privKey = cx->key;
147 SGNDigestInfo *di = 0;
148
149 result->data = 0;
150 digder.data = 0;
151
152 /* Finish up digest function */
153 if (cx->hashcx == NULL) {
154 PORT_SetError(SEC_ERROR_INVALID_ARGS);
155 return SECFailure;
156 }
157 (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest));
158
159 if (privKey->keyType == rsaKey) {
160
161 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
162 if (!arena) {
163 rv = SECFailure;
164 goto loser;
165 }
166
167 /* Construct digest info */
168 di = SGN_CreateDigestInfo(cx->hashalg, digest, part1);
169 if (!di) {
170 rv = SECFailure;
171 goto loser;
172 }
173
174 /* Der encode the digest as a DigestInfo */
175 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate,
176 di);
177 if (rv != SECSuccess) {
178 goto loser;
179 }
180 } else {
181 digder.data = digest;
182 digder.len = part1;
183 }
184
185 /*
186 ** Encrypt signature after constructing appropriate PKCS#1 signature
187 ** block
188 */
189 signatureLen = PK11_SignatureLen(privKey);
190 if (signatureLen <= 0) {
191 PORT_SetError(SEC_ERROR_INVALID_KEY);
192 rv = SECFailure;
193 goto loser;
194 }
195 sigitem.len = signatureLen;
196 sigitem.data = (unsigned char *)PORT_Alloc(signatureLen);
197
198 if (sigitem.data == NULL) {
199 rv = SECFailure;
200 goto loser;
201 }
202
203 rv = PK11_Sign(privKey, &sigitem, &digder);
204 if (rv != SECSuccess) {
205 PORT_Free(sigitem.data);
206 sigitem.data = NULL;
207 goto loser;
208 }
209
210 if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) ||
211 (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
212 /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */
213 rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len);
214 PORT_Free(sigitem.data);
215 if (rv != SECSuccess)
216 goto loser;
217 } else {
218 result->len = sigitem.len;
219 result->data = sigitem.data;
220 }
221
222 loser:
223 SGN_DestroyDigestInfo(di);
224 if (arena != NULL) {
225 PORT_FreeArena(arena, PR_FALSE);
226 }
227 return rv;
228 }
229
230 /************************************************************************/
231
232 /*
233 ** Sign a block of data returning in result a bunch of bytes that are the
234 ** signature. Returns zero on success, an error code on failure.
235 */
236 SECStatus
237 SEC_SignData(SECItem *res, const unsigned char *buf, int len,
238 SECKEYPrivateKey *pk, SECOidTag algid)
239 {
240 SECStatus rv;
241 SGNContext *sgn;
242
243 sgn = SGN_NewContext(algid, pk);
244
245 if (sgn == NULL)
246 return SECFailure;
247
248 rv = SGN_Begin(sgn);
249 if (rv != SECSuccess)
250 goto loser;
251
252 rv = SGN_Update(sgn, buf, len);
253 if (rv != SECSuccess)
254 goto loser;
255
256 rv = SGN_End(sgn, res);
257
258 loser:
259 SGN_DestroyContext(sgn, PR_TRUE);
260 return rv;
261 }
262
263 /************************************************************************/
264
265 DERTemplate CERTSignedDataTemplate[] =
266 {
267 { DER_SEQUENCE,
268 0, NULL, sizeof(CERTSignedData) },
269 { DER_ANY,
270 offsetof(CERTSignedData, data) },
271 { DER_INLINE,
272 offsetof(CERTSignedData, signatureAlgorithm),
273 SECAlgorithmIDTemplate },
274 { DER_BIT_STRING,
275 offsetof(CERTSignedData, signature) },
276 { 0 }
277 };
278
279 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
280
281 const SEC_ASN1Template CERT_SignedDataTemplate[] =
282 {
283 { SEC_ASN1_SEQUENCE,
284 0, NULL, sizeof(CERTSignedData) },
285 { SEC_ASN1_ANY,
286 offsetof(CERTSignedData, data) },
287 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
288 offsetof(CERTSignedData, signatureAlgorithm),
289 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
290 { SEC_ASN1_BIT_STRING,
291 offsetof(CERTSignedData, signature) },
292 { 0 }
293 };
294
295 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedDataTemplate)
296
297 SECStatus
298 SEC_DerSignData(PLArenaPool *arena, SECItem *result,
299 const unsigned char *buf, int len, SECKEYPrivateKey *pk,
300 SECOidTag algID)
301 {
302 SECItem it;
303 CERTSignedData sd;
304 SECStatus rv;
305
306 it.data = 0;
307
308 /* XXX We should probably have some asserts here to make sure the key type
309 * and algID match
310 */
311
312 if (algID == SEC_OID_UNKNOWN) {
313 switch (pk->keyType) {
314 case rsaKey:
315 algID = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
316 break;
317 case dsaKey:
318 /* get Signature length (= q_len*2) and work from there */
319 switch (PK11_SignatureLen(pk)) {
320 case 448:
321 algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST;
322 break;
323 case 512:
324 algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST;
325 break;
326 default:
327 algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
328 break;
329 }
330 break;
331 case ecKey:
332 algID = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
333 break;
334 default:
335 PORT_SetError(SEC_ERROR_INVALID_KEY);
336 return SECFailure;
337 }
338 }
339
340 /* Sign input buffer */
341 rv = SEC_SignData(&it, buf, len, pk, algID);
342 if (rv)
343 goto loser;
344
345 /* Fill out SignedData object */
346 PORT_Memset(&sd, 0, sizeof(sd));
347 sd.data.data = (unsigned char *)buf;
348 sd.data.len = len;
349 sd.signature.data = it.data;
350 sd.signature.len = it.len << 3; /* convert to bit string */
351 rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0);
352 if (rv)
353 goto loser;
354
355 /* DER encode the signed data object */
356 rv = DER_Encode(arena, result, CERTSignedDataTemplate, &sd);
357 /* FALL THROUGH */
358
359 loser:
360 PORT_Free(it.data);
361 return rv;
362 }
363
364 SECStatus
365 SGN_Digest(SECKEYPrivateKey *privKey,
366 SECOidTag algtag, SECItem *result, SECItem *digest)
367 {
368 int modulusLen;
369 SECStatus rv;
370 SECItem digder;
371 PLArenaPool *arena = 0;
372 SGNDigestInfo *di = 0;
373
374 result->data = 0;
375
376 if (privKey->keyType == rsaKey) {
377
378 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
379 if (!arena) {
380 rv = SECFailure;
381 goto loser;
382 }
383
384 /* Construct digest info */
385 di = SGN_CreateDigestInfo(algtag, digest->data, digest->len);
386 if (!di) {
387 rv = SECFailure;
388 goto loser;
389 }
390
391 /* Der encode the digest as a DigestInfo */
392 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate,
393 di);
394 if (rv != SECSuccess) {
395 goto loser;
396 }
397 } else {
398 digder.data = digest->data;
399 digder.len = digest->len;
400 }
401
402 /*
403 ** Encrypt signature after constructing appropriate PKCS#1 signature
404 ** block
405 */
406 modulusLen = PK11_SignatureLen(privKey);
407 if (modulusLen <= 0) {
408 PORT_SetError(SEC_ERROR_INVALID_KEY);
409 rv = SECFailure;
410 goto loser;
411 }
412 result->len = modulusLen;
413 result->data = (unsigned char *)PORT_Alloc(modulusLen);
414 result->type = siBuffer;
415
416 if (result->data == NULL) {
417 rv = SECFailure;
418 goto loser;
419 }
420
421 rv = PK11_Sign(privKey, result, &digder);
422 if (rv != SECSuccess) {
423 PORT_Free(result->data);
424 result->data = NULL;
425 }
426
427 loser:
428 SGN_DestroyDigestInfo(di);
429 if (arena != NULL) {
430 PORT_FreeArena(arena, PR_FALSE);
431 }
432 return rv;
433 }
434
435 SECOidTag
436 SEC_GetSignatureAlgorithmOidTag(KeyType keyType, SECOidTag hashAlgTag)
437 {
438 SECOidTag sigTag = SEC_OID_UNKNOWN;
439
440 switch (keyType) {
441 case rsaKey:
442 switch (hashAlgTag) {
443 case SEC_OID_MD2:
444 sigTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
445 break;
446 case SEC_OID_MD5:
447 sigTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
448 break;
449 case SEC_OID_SHA1:
450 sigTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
451 break;
452 case SEC_OID_SHA224:
453 sigTag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION;
454 break;
455 case SEC_OID_UNKNOWN: /* default for RSA if not specified */
456 case SEC_OID_SHA256:
457 sigTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
458 break;
459 case SEC_OID_SHA384:
460 sigTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
461 break;
462 case SEC_OID_SHA512:
463 sigTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
464 break;
465 default:
466 break;
467 }
468 break;
469 case dsaKey:
470 switch (hashAlgTag) {
471 case SEC_OID_UNKNOWN: /* default for DSA if not specified */
472 case SEC_OID_SHA1:
473 sigTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
474 break;
475 case SEC_OID_SHA224:
476 sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST;
477 break;
478 case SEC_OID_SHA256:
479 sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST;
480 break;
481 default:
482 break;
483 }
484 break;
485 case ecKey:
486 switch (hashAlgTag) {
487 case SEC_OID_UNKNOWN: /* default for ECDSA if not specified */
488 case SEC_OID_SHA1:
489 sigTag = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE;
490 break;
491 case SEC_OID_SHA224:
492 sigTag = SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE;
493 break;
494 case SEC_OID_SHA256:
495 sigTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
496 break;
497 case SEC_OID_SHA384:
498 sigTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
499 break;
500 case SEC_OID_SHA512:
501 sigTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
502 break;
503 default:
504 break;
505 }
506 default:
507 break;
508 }
509 return sigTag;
510 }
OLDNEW
« no previous file with comments | « nss/lib/cryptohi/seckey.c ('k') | nss/lib/cryptohi/secvfy.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698