comparison nss/lib/cryptohi/secsign.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
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
160 if (privKey->keyType == rsaKey) {
161
162 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
163 if ( !arena ) {
164 rv = SECFailure;
165 goto loser;
166 }
167
168 /* Construct digest info */
169 di = SGN_CreateDigestInfo(cx->hashalg, digest, part1);
170 if (!di) {
171 rv = SECFailure;
172 goto loser;
173 }
174
175 /* Der encode the digest as a DigestInfo */
176 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate,
177 di);
178 if (rv != SECSuccess) {
179 goto loser;
180 }
181 } else {
182 digder.data = digest;
183 digder.len = part1;
184 }
185
186 /*
187 ** Encrypt signature after constructing appropriate PKCS#1 signature
188 ** block
189 */
190 signatureLen = PK11_SignatureLen(privKey);
191 if (signatureLen <= 0) {
192 PORT_SetError(SEC_ERROR_INVALID_KEY);
193 rv = SECFailure;
194 goto loser;
195 }
196 sigitem.len = signatureLen;
197 sigitem.data = (unsigned char*) PORT_Alloc(signatureLen);
198
199 if (sigitem.data == NULL) {
200 rv = SECFailure;
201 goto loser;
202 }
203
204 rv = PK11_Sign(privKey, &sigitem, &digder);
205 if (rv != SECSuccess) {
206 PORT_Free(sigitem.data);
207 sigitem.data = NULL;
208 goto loser;
209 }
210
211 if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) ||
212 (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
213 /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */
214 rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len);
215 PORT_Free(sigitem.data);
216 if (rv != SECSuccess)
217 goto loser;
218 } else {
219 result->len = sigitem.len;
220 result->data = sigitem.data;
221 }
222
223 loser:
224 SGN_DestroyDigestInfo(di);
225 if (arena != NULL) {
226 PORT_FreeArena(arena, PR_FALSE);
227 }
228 return rv;
229 }
230
231 /************************************************************************/
232
233 /*
234 ** Sign a block of data returning in result a bunch of bytes that are the
235 ** signature. Returns zero on success, an error code on failure.
236 */
237 SECStatus
238 SEC_SignData(SECItem *res, const unsigned char *buf, int len,
239 SECKEYPrivateKey *pk, SECOidTag algid)
240 {
241 SECStatus rv;
242 SGNContext *sgn;
243
244
245 sgn = SGN_NewContext(algid, pk);
246
247 if (sgn == NULL)
248 return SECFailure;
249
250 rv = SGN_Begin(sgn);
251 if (rv != SECSuccess)
252 goto loser;
253
254 rv = SGN_Update(sgn, buf, len);
255 if (rv != SECSuccess)
256 goto loser;
257
258 rv = SGN_End(sgn, res);
259
260 loser:
261 SGN_DestroyContext(sgn, PR_TRUE);
262 return rv;
263 }
264
265 /************************************************************************/
266
267 DERTemplate CERTSignedDataTemplate[] =
268 {
269 { DER_SEQUENCE,
270 0, NULL, sizeof(CERTSignedData) },
271 { DER_ANY,
272 offsetof(CERTSignedData,data), },
273 { DER_INLINE,
274 offsetof(CERTSignedData,signatureAlgorithm),
275 SECAlgorithmIDTemplate, },
276 { DER_BIT_STRING,
277 offsetof(CERTSignedData,signature), },
278 { 0, }
279 };
280
281 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
282
283 const SEC_ASN1Template CERT_SignedDataTemplate[] =
284 {
285 { SEC_ASN1_SEQUENCE,
286 0, NULL, sizeof(CERTSignedData) },
287 { SEC_ASN1_ANY,
288 offsetof(CERTSignedData,data), },
289 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
290 offsetof(CERTSignedData,signatureAlgorithm),
291 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate), },
292 { SEC_ASN1_BIT_STRING,
293 offsetof(CERTSignedData,signature), },
294 { 0, }
295 };
296
297 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SignedDataTemplate)
298
299
300 SECStatus
301 SEC_DerSignData(PLArenaPool *arena, SECItem *result,
302 const unsigned char *buf, int len, SECKEYPrivateKey *pk,
303 SECOidTag algID)
304 {
305 SECItem it;
306 CERTSignedData sd;
307 SECStatus rv;
308
309 it.data = 0;
310
311 /* XXX We should probably have some asserts here to make sure the key type
312 * and algID match
313 */
314
315 if (algID == SEC_OID_UNKNOWN) {
316 switch(pk->keyType) {
317 case rsaKey:
318 algID = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
319 break;
320 case dsaKey:
321 /* get Signature length (= q_len*2) and work from there */
322 switch (PK11_SignatureLen(pk)) {
323 case 448:
324 algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST;
325 break;
326 case 512:
327 algID = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST;
328 break;
329 default:
330 algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
331 break;
332 }
333 break;
334 case ecKey:
335 algID = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
336 break;
337 default:
338 PORT_SetError(SEC_ERROR_INVALID_KEY);
339 return SECFailure;
340 }
341 }
342
343 /* Sign input buffer */
344 rv = SEC_SignData(&it, buf, len, pk, algID);
345 if (rv) goto loser;
346
347 /* Fill out SignedData object */
348 PORT_Memset(&sd, 0, sizeof(sd));
349 sd.data.data = (unsigned char*) buf;
350 sd.data.len = len;
351 sd.signature.data = it.data;
352 sd.signature.len = it.len << 3; /* convert to bit string */
353 rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0);
354 if (rv) goto loser;
355
356 /* DER encode the signed data object */
357 rv = DER_Encode(arena, result, CERTSignedDataTemplate, &sd);
358 /* FALL THROUGH */
359
360 loser:
361 PORT_Free(it.data);
362 return rv;
363 }
364
365 SECStatus
366 SGN_Digest(SECKEYPrivateKey *privKey,
367 SECOidTag algtag, SECItem *result, SECItem *digest)
368 {
369 int modulusLen;
370 SECStatus rv;
371 SECItem digder;
372 PLArenaPool *arena = 0;
373 SGNDigestInfo *di = 0;
374
375
376 result->data = 0;
377
378 if (privKey->keyType == rsaKey) {
379
380 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
381 if ( !arena ) {
382 rv = SECFailure;
383 goto loser;
384 }
385
386 /* Construct digest info */
387 di = SGN_CreateDigestInfo(algtag, digest->data, digest->len);
388 if (!di) {
389 rv = SECFailure;
390 goto loser;
391 }
392
393 /* Der encode the digest as a DigestInfo */
394 rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate,
395 di);
396 if (rv != SECSuccess) {
397 goto loser;
398 }
399 } else {
400 digder.data = digest->data;
401 digder.len = digest->len;
402 }
403
404 /*
405 ** Encrypt signature after constructing appropriate PKCS#1 signature
406 ** block
407 */
408 modulusLen = PK11_SignatureLen(privKey);
409 if (modulusLen <= 0) {
410 PORT_SetError(SEC_ERROR_INVALID_KEY);
411 rv = SECFailure;
412 goto loser;
413 }
414 result->len = modulusLen;
415 result->data = (unsigned char*) PORT_Alloc(modulusLen);
416
417 if (result->data == NULL) {
418 rv = SECFailure;
419 goto loser;
420 }
421
422 rv = PK11_Sign(privKey, result, &digder);
423 if (rv != SECSuccess) {
424 PORT_Free(result->data);
425 result->data = NULL;
426 }
427
428 loser:
429 SGN_DestroyDigestInfo(di);
430 if (arena != NULL) {
431 PORT_FreeArena(arena, PR_FALSE);
432 }
433 return rv;
434 }
435
436 SECOidTag
437 SEC_GetSignatureAlgorithmOidTag(KeyType keyType, SECOidTag hashAlgTag)
438 {
439 SECOidTag sigTag = SEC_OID_UNKNOWN;
440
441 switch (keyType) {
442 case rsaKey:
443 switch (hashAlgTag) {
444 case SEC_OID_MD2:
445 sigTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION; break;
446 case SEC_OID_MD5:
447 sigTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; break;
448 case SEC_OID_UNKNOWN: /* default for RSA if not specified */
449 case SEC_OID_SHA1:
450 sigTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; break;
451 case SEC_OID_SHA224:
452 sigTag = SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION; break;
453 case SEC_OID_SHA256:
454 sigTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; break;
455 case SEC_OID_SHA384:
456 sigTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; break;
457 case SEC_OID_SHA512:
458 sigTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; break;
459 default:
460 break;
461 }
462 break;
463 case dsaKey:
464 switch (hashAlgTag) {
465 case SEC_OID_UNKNOWN: /* default for DSA if not specified */
466 case SEC_OID_SHA1:
467 sigTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; break;
468 case SEC_OID_SHA224:
469 sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST; break;
470 case SEC_OID_SHA256:
471 sigTag = SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST; break;
472 default:
473 break;
474 }
475 break;
476 case ecKey:
477 switch (hashAlgTag) {
478 case SEC_OID_UNKNOWN: /* default for ECDSA if not specified */
479 case SEC_OID_SHA1:
480 sigTag = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE; break;
481 case SEC_OID_SHA224:
482 sigTag = SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE; break;
483 case SEC_OID_SHA256:
484 sigTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; break;
485 case SEC_OID_SHA384:
486 sigTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; break;
487 case SEC_OID_SHA512:
488 sigTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE; break;
489 default:
490 break;
491 }
492 default:
493 break;
494 }
495 return sigTag;
496 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)