1 #include "system.h"
2 
3 #include <pthread.h>
4 #include <nss.h>
5 #include <sechash.h>
6 #include <signal.h>
7 #include <keyhi.h>
8 #include <cryptohi.h>
9 #include <blapit.h>
10 
11 #include <rpm/rpmlog.h>
12 #include "rpmio/digest.h"
13 #include "debug.h"
14 
15 
16 static int _crypto_initialized = 0;
17 static int _new_process = 1;
18 
19 #if HAVE_NSS_INITCONTEXT
20 static NSSInitContext * _nss_ctx = NULL;
21 #endif
22 
23 /**
24  * MD5/SHA1 digest private data.
25  */
26 struct DIGEST_CTX_s {
27     rpmDigestFlags flags;	/*!< Bit(s) to control digest operation. */
28     HASHContext *hashctx;	/*!< Internal NSS hash context. */
29     int algo;			/*!< Used hash algorithm */
30 };
31 
32 /*
33  * Only flag for re-initialization here, in the common case the child
34  * exec()'s something else shutting down NSS here would be waste of time.
35  */
at_forkchild(void)36 static void at_forkchild(void)
37 {
38     _new_process = 1;
39 }
40 
rpmInitCrypto(void)41 int rpmInitCrypto(void)
42 {
43     int rc = 0;
44 
45     /* Lazy NSS shutdown for re-initialization after fork() */
46     if (_new_process && _crypto_initialized) {
47 	rpmFreeCrypto();
48     }
49 
50     /*
51      * Initialize NSS if not already done.
52      * NSS prior to 3.12.5 only supports a global context which can cause
53      * trouble when an API user wants to use NSS for their own purposes, use
54      * a private context if possible.
55      */
56     if (!_crypto_initialized) {
57 	/* NSPR sets SIGPIPE to ignore behind our back, save and restore */
58 	struct sigaction oact;
59 	sigaction(SIGPIPE, NULL, &oact);
60 #if HAVE_NSS_INITCONTEXT
61 	PRUint32 flags = (NSS_INIT_READONLY|NSS_INIT_NOCERTDB|
62 			  NSS_INIT_NOMODDB|NSS_INIT_FORCEOPEN|
63 			  NSS_INIT_NOROOTINIT|NSS_INIT_OPTIMIZESPACE);
64 	_nss_ctx = NSS_InitContext(NULL, NULL, NULL, NULL, NULL, flags);
65 	if (_nss_ctx == NULL) {
66 #else
67 	if (NSS_NoDB_Init(NULL) != SECSuccess) {
68 #endif
69 	    rpmlog(RPMLOG_ERR, _("Failed to initialize NSS library\n"));
70 	    rc = -1;
71 	} else {
72 	    _crypto_initialized = 1;
73 	}
74 	sigaction(SIGPIPE, &oact, NULL);
75     }
76 
77     /* Register one post-fork handler per process */
78     if (_new_process) {
79 	if (pthread_atfork(NULL, NULL, at_forkchild) != 0) {
80 	    rpmlog(RPMLOG_WARNING, _("Failed to register fork handler: %m\n"));
81 	}
82 	_new_process = 0;
83     }
84     return rc;
85 }
86 
87 int rpmFreeCrypto(void)
88 {
89     int rc = 0;
90     if (_crypto_initialized) {
91 #if HAVE_NSS_INITCONTEXT
92 	rc = (NSS_ShutdownContext(_nss_ctx) != SECSuccess);
93 	_nss_ctx = NULL;
94 #else
95 	rc = (NSS_Shutdown() != SECSuccess);
96 #endif
97     	_crypto_initialized = 0;
98     }
99     return rc;
100 }
101 
102 DIGEST_CTX rpmDigestDup(DIGEST_CTX octx)
103 {
104     DIGEST_CTX nctx = NULL;
105     if (octx) {
106 	HASHContext *hctx = HASH_Clone(octx->hashctx);
107 	if (hctx) {
108 	    nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
109 	    nctx->hashctx = hctx;
110 	}
111     }
112     return nctx;
113 }
114 
115 RPM_GNUC_PURE
116 static HASH_HashType getHashType(int hashalgo)
117 {
118     switch (hashalgo) {
119     case PGPHASHALGO_MD5:	return HASH_AlgMD5;
120     case PGPHASHALGO_SHA1:	return HASH_AlgSHA1;
121 #ifdef SHA224_LENGTH
122     case PGPHASHALGO_SHA224:	return HASH_AlgSHA224;
123 #endif
124     case PGPHASHALGO_SHA256:	return HASH_AlgSHA256;
125     case PGPHASHALGO_SHA384:	return HASH_AlgSHA384;
126     case PGPHASHALGO_SHA512:	return HASH_AlgSHA512;
127     }
128     return HASH_AlgNULL;
129 }
130 
131 size_t rpmDigestLength(int hashalgo)
132 {
133     return HASH_ResultLen(getHashType(hashalgo));
134 }
135 
136 DIGEST_CTX rpmDigestInit(int hashalgo, rpmDigestFlags flags)
137 {
138     HASH_HashType type = getHashType(hashalgo);
139     HASHContext *hashctx = NULL;
140     DIGEST_CTX ctx = NULL;
141 
142     if (type == HASH_AlgNULL || rpmInitCrypto() < 0)
143 	goto exit;
144 
145     if ((hashctx = HASH_Create(type)) != NULL) {
146 	ctx = xcalloc(1, sizeof(*ctx));
147 	ctx->flags = flags;
148 	ctx->algo = hashalgo;
149 	ctx->hashctx = hashctx;
150     	HASH_Begin(ctx->hashctx);
151     }
152 
153 exit:
154     return ctx;
155 }
156 
157 int rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
158 {
159     size_t partlen;
160     const unsigned char *ptr = data;
161 
162     if (ctx == NULL)
163 	return -1;
164 
165    partlen = ~(unsigned int)0xFF;
166    while (len > 0) {
167    	if (len < partlen) {
168    		partlen = len;
169    	}
170 	HASH_Update(ctx->hashctx, ptr, partlen);
171 	ptr += partlen;
172 	len -= partlen;
173    }
174    return 0;
175 }
176 
177 int rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
178 {
179     unsigned char * digest;
180     unsigned int digestlen;
181 
182     if (ctx == NULL)
183 	return -1;
184     digestlen = HASH_ResultLenContext(ctx->hashctx);
185     digest = xmalloc(digestlen);
186 
187 /* FIX: check rc */
188     HASH_End(ctx->hashctx, digest, (unsigned int *) &digestlen, digestlen);
189 
190     /* Return final digest. */
191     if (!asAscii) {
192 	if (lenp) *lenp = digestlen;
193 	if (datap) {
194 	    *datap = digest;
195 	    digest = NULL;
196 	}
197     } else {
198 	if (lenp) *lenp = (2*digestlen) + 1;
199 	if (datap) {
200 	    const uint8_t * s = (const uint8_t *) digest;
201 	    *datap = pgpHexStr(s, digestlen);
202 	}
203     }
204     if (digest) {
205 	memset(digest, 0, digestlen);	/* In case it's sensitive */
206 	free(digest);
207     }
208     HASH_Destroy(ctx->hashctx);
209     memset(ctx, 0, sizeof(*ctx));	/* In case it's sensitive */
210     free(ctx);
211     return 0;
212 }
213 
214 RPM_GNUC_PURE
215 static SECOidTag getHashAlg(unsigned int hashalgo)
216 {
217     switch (hashalgo) {
218     case PGPHASHALGO_MD5:	return SEC_OID_MD5;
219     case PGPHASHALGO_SHA1:	return SEC_OID_SHA1;
220 #ifdef SHA224_LENGTH
221     case PGPHASHALGO_SHA224:	return SEC_OID_SHA224;
222 #endif
223     case PGPHASHALGO_SHA256:	return SEC_OID_SHA256;
224     case PGPHASHALGO_SHA384:	return SEC_OID_SHA384;
225     case PGPHASHALGO_SHA512:	return SEC_OID_SHA512;
226     }
227     return SEC_OID_UNKNOWN;
228 }
229 
230 static int pgpMpiSet(unsigned int lbits, uint8_t *dest, const uint8_t * p)
231 {
232     unsigned int mbits = pgpMpiBits(p);
233     unsigned int nbits;
234     size_t nbytes;
235     uint8_t *t = dest;
236     unsigned int ix;
237 
238     if (mbits > lbits)
239 	return 1;
240 
241     nbits = (lbits > mbits ? lbits : mbits);
242     nbytes = ((nbits + 7) >> 3);
243     ix = (nbits - mbits) >> 3;
244 
245     if (ix > 0)
246 	memset(t, '\0', ix);
247     memcpy(t+ix, p+2, nbytes-ix);
248 
249     return 0;
250 }
251 
252 static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p)
253 {
254     size_t nbytes = pgpMpiLen(p)-2;
255 
256     if (item == NULL) {
257     	if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL)
258     	    return item;
259     } else {
260     	if (arena != NULL)
261     	    item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
262     	else
263     	    item->data = PORT_Realloc(item->data, nbytes);
264 
265     	if (item->data == NULL) {
266     	    if (arena == NULL)
267     		SECITEM_FreeItem(item, PR_TRUE);
268     	    return NULL;
269     	}
270     }
271 
272     memcpy(item->data, p+2, nbytes);
273     item->len = nbytes;
274     return item;
275 }
276 
277 static SECKEYPublicKey *pgpNewPublicKey(KeyType type)
278 {
279     PRArenaPool *arena;
280     SECKEYPublicKey *key;
281 
282     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
283     if (arena == NULL)
284 	return NULL;
285 
286     key = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
287 
288     if (key == NULL) {
289 	PORT_FreeArena(arena, PR_FALSE);
290 	return NULL;
291     }
292 
293     key->keyType = type;
294     key->pkcs11ID = CK_INVALID_HANDLE;
295     key->pkcs11Slot = NULL;
296     key->arena = arena;
297     return key;
298 }
299 
300 /* compatibility with nss < 3.14 */
301 #ifndef DSA1_SUBPRIME_LEN
302 #define DSA1_SUBPRIME_LEN DSA_SUBPRIME_LEN
303 #endif
304 #ifndef DSA1_SIGNATURE_LEN
305 #define DSA1_SIGNATURE_LEN DSA_SIGNATURE_LEN
306 #endif
307 #ifndef DSA1_Q_BITS
308 #define DSA1_Q_BITS DSA_Q_BITS
309 #endif
310 
311 static int pgpSetSigMpiDSA(pgpDigAlg pgpsig, int num, const uint8_t *p)
312 {
313     SECItem *sig = pgpsig->data;
314     unsigned int qbits = DSA1_Q_BITS;
315     unsigned int subprlen = DSA1_SUBPRIME_LEN;
316     unsigned int siglen = DSA1_SIGNATURE_LEN;
317     int rc = 1; /* assume failure */
318 
319     switch (num) {
320     case 0:
321 	sig = pgpsig->data = SECITEM_AllocItem(NULL, NULL, siglen);
322 	if (sig) {
323 	    memset(sig->data, 0, siglen);
324 	    rc = pgpMpiSet(qbits, sig->data, p);
325 	}
326 	break;
327     case 1:
328 	if (sig && pgpMpiSet(qbits, sig->data+subprlen, p) == 0) {
329 	    SECItem *signew = SECITEM_AllocItem(NULL, NULL, 0);
330 	    if (signew == NULL)
331 		break;
332 	    if (DSAU_EncodeDerSigWithLen(signew, sig, siglen) == SECSuccess) {
333 		SECITEM_FreeItem(sig, PR_TRUE);
334 		pgpsig->data = signew;
335 		rc = 0;
336 	    }
337 	}
338 	break;
339     }
340 
341     return rc;
342 }
343 
344 static int pgpSetKeyMpiDSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
345 {
346     SECItem *mpi = NULL;
347     SECKEYPublicKey *key = pgpkey->data;
348 
349     if (key == NULL)
350 	key = pgpkey->data = pgpNewPublicKey(dsaKey);
351 
352     if (key) {
353 	switch (num) {
354 	case 0:
355 	    mpi = pgpMpiItem(key->arena, &key->u.dsa.params.prime, p);
356 	    break;
357 	case 1:
358 	    mpi = pgpMpiItem(key->arena, &key->u.dsa.params.subPrime, p);
359 	    break;
360 	case 2:
361 	    mpi = pgpMpiItem(key->arena, &key->u.dsa.params.base, p);
362 	    break;
363 	case 3:
364 	    mpi = pgpMpiItem(key->arena, &key->u.dsa.publicValue, p);
365 	    break;
366 	}
367     }
368 
369     return (mpi == NULL);
370 }
371 
372 static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
373 			   uint8_t *hash, size_t hashlen, int hash_algo)
374 {
375     SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
376     SECOidTag encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE;
377     SECOidTag hashAlg = getHashAlg(hash_algo);
378     SECStatus rc;
379 
380     if (hashAlg == SEC_OID_UNKNOWN)
381 	return 1;
382 
383     rc = VFY_VerifyDigestDirect(&digest, pgpkey->data, pgpsig->data,
384 				encAlg, hashAlg, NULL);
385 
386     return (rc != SECSuccess);
387 }
388 
389 static int pgpSetSigMpiRSA(pgpDigAlg pgpsig, int num, const uint8_t *p)
390 {
391     SECItem *sigitem = NULL;
392 
393     if (num == 0) {
394        sigitem = pgpMpiItem(NULL, pgpsig->data, p);
395        if (sigitem)
396            pgpsig->data = sigitem;
397     }
398     return (sigitem == NULL);
399 }
400 
401 static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
402 {
403     SECItem *kitem = NULL;
404     SECKEYPublicKey *key = pgpkey->data;
405 
406     if (key == NULL)
407 	key = pgpkey->data = pgpNewPublicKey(rsaKey);
408 
409     if (key) {
410 	switch (num) {
411 	case 0:
412 	    kitem = pgpMpiItem(key->arena, &key->u.rsa.modulus, p);
413 	    break;
414 	case 1:
415 	    kitem = pgpMpiItem(key->arena, &key->u.rsa.publicExponent, p);
416 	    break;
417 	}
418     }
419 
420     return (kitem == NULL);
421 }
422 
423 static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
424 			   uint8_t *hash, size_t hashlen, int hash_algo)
425 {
426     SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
427     SECItem *sig = pgpsig->data;
428     SECKEYPublicKey *key = pgpkey->data;
429     SECItem *padded = NULL;
430     SECOidTag encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
431     SECOidTag hashAlg = getHashAlg(hash_algo);
432     SECStatus rc = SECFailure;
433     size_t siglen, padlen;
434 
435     if (hashAlg == SEC_OID_UNKNOWN)
436 	return 1;
437 
438     /* Zero-pad signature to expected size if necessary */
439     siglen = SECKEY_SignatureLen(key);
440     padlen = siglen - sig->len;
441     if (padlen) {
442 	padded = SECITEM_AllocItem(NULL, NULL, siglen);
443 	if (padded == NULL)
444 	    return 1;
445 	memset(padded->data, 0, padlen);
446 	memcpy(padded->data + padlen, sig->data, sig->len);
447 	sig = padded;
448     }
449 
450     rc = VFY_VerifyDigestDirect(&digest, key, sig, encAlg, hashAlg, NULL);
451 
452     if (padded)
453 	SECITEM_ZfreeItem(padded, PR_TRUE);
454 
455     return (rc != SECSuccess);
456 }
457 
458 static void pgpFreeSigRSADSA(pgpDigAlg sa)
459 {
460     SECITEM_ZfreeItem(sa->data, PR_TRUE);
461     sa->data = NULL;
462 }
463 
464 static void pgpFreeKeyRSADSA(pgpDigAlg ka)
465 {
466     SECKEY_DestroyPublicKey(ka->data);
467     ka->data = NULL;
468 }
469 
470 static int pgpSetMpiNULL(pgpDigAlg pgpkey, int num, const uint8_t *p)
471 {
472     return 1;
473 }
474 
475 static int pgpVerifyNULL(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
476 			 uint8_t *hash, size_t hashlen, int hash_algo)
477 {
478     return 1;
479 }
480 
481 pgpDigAlg pgpPubkeyNew(int algo, int curve)
482 {
483     pgpDigAlg ka = xcalloc(1, sizeof(*ka));;
484 
485     switch (algo) {
486     case PGPPUBKEYALGO_RSA:
487 	ka->setmpi = pgpSetKeyMpiRSA;
488 	ka->free = pgpFreeKeyRSADSA;
489 	ka->mpis = 2;
490 	break;
491     case PGPPUBKEYALGO_DSA:
492 	ka->setmpi = pgpSetKeyMpiDSA;
493 	ka->free = pgpFreeKeyRSADSA;
494 	ka->mpis = 4;
495 	break;
496     default:
497 	ka->setmpi = pgpSetMpiNULL;
498 	ka->mpis = -1;
499 	break;
500     }
501 
502     ka->verify = pgpVerifyNULL; /* keys can't be verified */
503 
504     return ka;
505 }
506 
507 pgpDigAlg pgpSignatureNew(int algo)
508 {
509     pgpDigAlg sa = xcalloc(1, sizeof(*sa));
510 
511     switch (algo) {
512     case PGPPUBKEYALGO_RSA:
513 	sa->setmpi = pgpSetSigMpiRSA;
514 	sa->free = pgpFreeSigRSADSA;
515 	sa->verify = pgpVerifySigRSA;
516 	sa->mpis = 1;
517 	break;
518     case PGPPUBKEYALGO_DSA:
519 	sa->setmpi = pgpSetSigMpiDSA;
520 	sa->free = pgpFreeSigRSADSA;
521 	sa->verify = pgpVerifySigDSA;
522 	sa->mpis = 2;
523 	break;
524     default:
525 	sa->setmpi = pgpSetMpiNULL;
526 	sa->verify = pgpVerifyNULL;
527 	sa->mpis = -1;
528 	break;
529     }
530     return sa;
531 }
532 
533