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