Imported Upstream version 4.14.1
[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         /* NSPR sets SIGPIPE to ignore behind our back, save and restore */
57         struct sigaction oact;
58         sigaction(SIGPIPE, NULL, &oact);
59 #if HAVE_NSS_INITCONTEXT
60         PRUint32 flags = (NSS_INIT_READONLY|NSS_INIT_NOCERTDB|
61                           NSS_INIT_NOMODDB|NSS_INIT_FORCEOPEN|
62                           NSS_INIT_NOROOTINIT|NSS_INIT_OPTIMIZESPACE);
63         _nss_ctx = NSS_InitContext(NULL, NULL, NULL, NULL, NULL, flags);
64         if (_nss_ctx == NULL) {
65 #else
66         if (NSS_NoDB_Init(NULL) != SECSuccess) {
67 #endif
68             rpmlog(RPMLOG_ERR, _("Failed to initialize NSS library\n"));
69             rc = -1;
70         } else {
71             _crypto_initialized = 1;
72         }
73         sigaction(SIGPIPE, &oact, NULL);
74     }
75
76     /* Register one post-fork handler per process */
77     if (_new_process) {
78         if (pthread_atfork(NULL, NULL, at_forkchild) != 0) {
79             rpmlog(RPMLOG_WARNING, _("Failed to register fork handler: %m\n"));
80         }
81         _new_process = 0;
82     }
83     return rc;
84 }
85
86 int rpmFreeCrypto(void) 
87 {
88     int rc = 0;
89     if (_crypto_initialized) {
90 #if HAVE_NSS_INITCONTEXT
91         rc = (NSS_ShutdownContext(_nss_ctx) != SECSuccess);
92         _nss_ctx = NULL;
93 #else
94         rc = (NSS_Shutdown() != SECSuccess);
95 #endif
96         _crypto_initialized = 0;
97     }
98     return rc;
99 }
100
101 DIGEST_CTX rpmDigestDup(DIGEST_CTX octx)
102 {
103     DIGEST_CTX nctx = NULL;
104     if (octx) {
105         HASHContext *hctx = HASH_Clone(octx->hashctx);
106         if (hctx) {
107             nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
108             nctx->hashctx = hctx;
109         }
110     }
111     return nctx;
112 }
113
114 RPM_GNUC_PURE
115 static HASH_HashType getHashType(int hashalgo)
116 {
117     switch (hashalgo) {
118     case PGPHASHALGO_MD5:       return HASH_AlgMD5;
119     case PGPHASHALGO_MD2:       return HASH_AlgMD2;
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_MD2:       return SEC_OID_MD2;
220     case PGPHASHALGO_SHA1:      return SEC_OID_SHA1;
221 #ifdef SHA224_LENGTH
222     case PGPHASHALGO_SHA224:    return SEC_OID_SHA224;
223 #endif
224     case PGPHASHALGO_SHA256:    return SEC_OID_SHA256;
225     case PGPHASHALGO_SHA384:    return SEC_OID_SHA384;
226     case PGPHASHALGO_SHA512:    return SEC_OID_SHA512;
227     }
228     return SEC_OID_UNKNOWN;
229 }
230
231 static int pgpMpiSet(unsigned int lbits, uint8_t *dest, const uint8_t * p)
232 {
233     unsigned int mbits = pgpMpiBits(p);
234     unsigned int nbits;
235     size_t nbytes;
236     uint8_t *t = dest;
237     unsigned int ix;
238
239     if (mbits > lbits)
240         return 1;
241
242     nbits = (lbits > mbits ? lbits : mbits);
243     nbytes = ((nbits + 7) >> 3);
244     ix = (nbits - mbits) >> 3;
245
246     if (ix > 0)
247         memset(t, '\0', ix);
248     memcpy(t+ix, p+2, nbytes-ix);
249
250     return 0;
251 }
252
253 static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p)
254 {
255     size_t nbytes = pgpMpiLen(p)-2;
256
257     if (item == NULL) {
258         if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL)
259             return item;
260     } else {
261         if (arena != NULL)
262             item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
263         else
264             item->data = PORT_Realloc(item->data, nbytes);
265         
266         if (item->data == NULL) {
267             if (arena == NULL)
268                 SECITEM_FreeItem(item, PR_TRUE);
269             return NULL;
270         }
271     }
272
273     memcpy(item->data, p+2, nbytes);
274     item->len = nbytes;
275     return item;
276 }
277
278 static SECKEYPublicKey *pgpNewPublicKey(KeyType type)
279 {
280     PRArenaPool *arena;
281     SECKEYPublicKey *key;
282     
283     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
284     if (arena == NULL)
285         return NULL;
286     
287     key = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
288     
289     if (key == NULL) {
290         PORT_FreeArena(arena, PR_FALSE);
291         return NULL;
292     }
293     
294     key->keyType = type;
295     key->pkcs11ID = CK_INVALID_HANDLE;
296     key->pkcs11Slot = NULL;
297     key->arena = arena;
298     return key;
299 }
300
301 /* compatibility with nss < 3.14 */
302 #ifndef DSA1_SUBPRIME_LEN
303 #define DSA1_SUBPRIME_LEN DSA_SUBPRIME_LEN
304 #endif
305 #ifndef DSA1_SIGNATURE_LEN
306 #define DSA1_SIGNATURE_LEN DSA_SIGNATURE_LEN
307 #endif
308 #ifndef DSA1_Q_BITS
309 #define DSA1_Q_BITS DSA_Q_BITS
310 #endif
311
312 static int pgpSetSigMpiDSA(pgpDigAlg pgpsig, int num, const uint8_t *p)
313 {
314     SECItem *sig = pgpsig->data;
315     unsigned int qbits = DSA1_Q_BITS;
316     unsigned int subprlen = DSA1_SUBPRIME_LEN;
317     unsigned int siglen = DSA1_SIGNATURE_LEN;
318     int rc = 1; /* assume failure */
319
320     switch (num) {
321     case 0:
322         sig = pgpsig->data = SECITEM_AllocItem(NULL, NULL, siglen);
323         if (sig) {
324             memset(sig->data, 0, siglen);
325             rc = pgpMpiSet(qbits, sig->data, p);
326         }
327         break;
328     case 1:
329         if (sig && pgpMpiSet(qbits, sig->data+subprlen, p) == 0) {
330             SECItem *signew = SECITEM_AllocItem(NULL, NULL, 0);
331             if (signew == NULL)
332                 break;
333             if (DSAU_EncodeDerSigWithLen(signew, sig, siglen) == 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, const uint8_t *p)
346 {
347     SECItem *mpi = NULL;
348     SECKEYPublicKey *key = pgpkey->data;
349
350     if (key == NULL)
351         key = pgpkey->data = pgpNewPublicKey(dsaKey);
352
353     if (key) {
354         switch (num) {
355         case 0:
356             mpi = pgpMpiItem(key->arena, &key->u.dsa.params.prime, p);
357             break;
358         case 1:
359             mpi = pgpMpiItem(key->arena, &key->u.dsa.params.subPrime, p);
360             break;
361         case 2:
362             mpi = pgpMpiItem(key->arena, &key->u.dsa.params.base, p);
363             break;
364         case 3:
365             mpi = pgpMpiItem(key->arena, &key->u.dsa.publicValue, p);
366             break;
367         }
368     }
369
370     return (mpi == NULL);
371 }
372
373 static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
374                            uint8_t *hash, size_t hashlen, int hash_algo)
375 {
376     SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
377     SECOidTag encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE;
378     SECOidTag hashAlg = getHashAlg(hash_algo);
379     SECStatus rc;
380
381     if (hashAlg == SEC_OID_UNKNOWN)
382         return 1;
383
384     rc = VFY_VerifyDigestDirect(&digest, pgpkey->data, pgpsig->data,
385                                 encAlg, hashAlg, NULL);
386
387     return (rc != SECSuccess);
388 }
389
390 static int pgpSetSigMpiRSA(pgpDigAlg pgpsig, int num, const uint8_t *p)
391 {
392     SECItem *sigitem = NULL;
393
394     if (num == 0) {
395        sigitem = pgpMpiItem(NULL, pgpsig->data, p);
396        if (sigitem)
397            pgpsig->data = sigitem;
398     }
399     return (sigitem == NULL);
400 }
401
402 static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
403 {
404     SECItem *kitem = NULL;
405     SECKEYPublicKey *key = pgpkey->data;
406
407     if (key == NULL)
408         key = pgpkey->data = pgpNewPublicKey(rsaKey);
409
410     if (key) {
411         switch (num) {
412         case 0:
413             kitem = pgpMpiItem(key->arena, &key->u.rsa.modulus, p);
414             break;
415         case 1:
416             kitem = pgpMpiItem(key->arena, &key->u.rsa.publicExponent, p);
417             break;
418         }
419     }
420
421     return (kitem == NULL);
422 }
423
424 static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
425                            uint8_t *hash, size_t hashlen, int hash_algo)
426 {
427     SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
428     SECItem *sig = pgpsig->data;
429     SECKEYPublicKey *key = pgpkey->data;
430     SECItem *padded = NULL;
431     SECOidTag encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
432     SECOidTag hashAlg = getHashAlg(hash_algo);
433     SECStatus rc = SECFailure;
434     size_t siglen, padlen;
435
436     if (hashAlg == SEC_OID_UNKNOWN)
437         return 1;
438
439     /* Zero-pad signature to expected size if necessary */
440     siglen = SECKEY_SignatureLen(key);
441     padlen = siglen - sig->len;
442     if (padlen) {
443         padded = SECITEM_AllocItem(NULL, NULL, siglen);
444         if (padded == NULL)
445             return 1;
446         memset(padded->data, 0, padlen);
447         memcpy(padded->data + padlen, sig->data, sig->len);
448         sig = padded;
449     }
450
451     rc = VFY_VerifyDigestDirect(&digest, key, sig, encAlg, hashAlg, NULL);
452
453     if (padded)
454         SECITEM_ZfreeItem(padded, PR_TRUE);
455
456     return (rc != SECSuccess);
457 }
458
459 static void pgpFreeSigRSADSA(pgpDigAlg sa)
460 {
461     SECITEM_ZfreeItem(sa->data, PR_TRUE);
462     sa->data = NULL;
463 }
464
465 static void pgpFreeKeyRSADSA(pgpDigAlg ka)
466 {
467     SECKEY_DestroyPublicKey(ka->data);
468     ka->data = NULL;
469 }
470
471 static int pgpSetMpiNULL(pgpDigAlg pgpkey, int num, const uint8_t *p)
472 {
473     return 1;
474 }
475
476 static int pgpVerifyNULL(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
477                          uint8_t *hash, size_t hashlen, int hash_algo)
478 {
479     return 1;
480 }
481
482 pgpDigAlg pgpPubkeyNew(int algo)
483 {
484     pgpDigAlg ka = xcalloc(1, sizeof(*ka));;
485
486     switch (algo) {
487     case PGPPUBKEYALGO_RSA:
488         ka->setmpi = pgpSetKeyMpiRSA;
489         ka->free = pgpFreeKeyRSADSA;
490         ka->mpis = 2;
491         break;
492     case PGPPUBKEYALGO_DSA:
493         ka->setmpi = pgpSetKeyMpiDSA;
494         ka->free = pgpFreeKeyRSADSA;
495         ka->mpis = 4;
496         break;
497     default:
498         ka->setmpi = pgpSetMpiNULL;
499         ka->mpis = -1;
500         break;
501     }
502
503     ka->verify = pgpVerifyNULL; /* keys can't be verified */
504
505     return ka;
506 }
507
508 pgpDigAlg pgpSignatureNew(int algo)
509 {
510     pgpDigAlg sa = xcalloc(1, sizeof(*sa));
511
512     switch (algo) {
513     case PGPPUBKEYALGO_RSA:
514         sa->setmpi = pgpSetSigMpiRSA;
515         sa->free = pgpFreeSigRSADSA;
516         sa->verify = pgpVerifySigRSA;
517         sa->mpis = 1;
518         break;
519     case PGPPUBKEYALGO_DSA:
520         sa->setmpi = pgpSetSigMpiDSA;
521         sa->free = pgpFreeSigRSADSA;
522         sa->verify = pgpVerifySigDSA;
523         sa->mpis = 2;
524         break;
525     default:
526         sa->setmpi = pgpSetMpiNULL;
527         sa->verify = pgpVerifyNULL;
528         sa->mpis = -1;
529         break;
530     }
531     return sa;
532 }
533