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

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

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

Powered by Google App Engine
This is Rietveld 408576698