rpm  5.2.1
rpmnss.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmiotypes.h>
8 #define _RPMPGP_INTERNAL
9 #if defined(WITH_NSS)
10 #define _RPMNSS_INTERNAL
11 #include <rpmnss.h>
12 #endif
13 
14 #include "debug.h"
15 
16 #if defined(WITH_NSS)
17 
18 /*@access pgpDig @*/
19 /*@access pgpDigParams @*/
20 
21 /*@-redecl@*/
22 /*@unchecked@*/
23 extern int _pgp_debug;
24 
25 /*@unchecked@*/
26 extern int _pgp_print;
27 /*@=redecl@*/
28 
29 /*@unchecked@*/
30 extern int _rpmnss_init;
31 
32 static
33 int rpmnssSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
34  /*@modifies dig @*/
35 {
36  rpmnss nss = dig->impl;
37  int xx;
38 
39 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
40  nss->sigalg = SEC_OID_UNKNOWN;
41  switch (sigp->hash_algo) {
42  case PGPHASHALGO_MD5:
43  nss->sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
44  break;
45  case PGPHASHALGO_SHA1:
46  nss->sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
47  break;
49  break;
50  case PGPHASHALGO_MD2:
51  nss->sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
52  break;
53  case PGPHASHALGO_MD4:
54  nss->sigalg = SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION;
55  break;
57  break;
59  break;
60  case PGPHASHALGO_SHA256:
61  nss->sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
62  break;
63  case PGPHASHALGO_SHA384:
64  nss->sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
65  break;
66  case PGPHASHALGO_SHA512:
67  nss->sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
68  break;
69  case PGPHASHALGO_SHA224:
70  break;
71  default:
72  break;
73  }
74  if (nss->sigalg == SEC_OID_UNKNOWN)
75  return 1;
76 
77  xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 0);
78 
79  /* Compare leading 16 bits of digest for quick check. */
80  return memcmp(dig->md5, sigp->signhash16, sizeof(sigp->signhash16));
81 }
82 
83 static
84 int rpmnssVerifyRSA(pgpDig dig)
85  /*@*/
86 {
87  rpmnss nss = dig->impl;
88  int rc;
89 
90  nss->item.type = siBuffer;
91  nss->item.data = dig->md5;
92  nss->item.len = (unsigned) dig->md5len;
93 
94 /*@-moduncon -nullstate @*/
95  rc = (VFY_VerifyDigest(&nss->item, nss->rsa, nss->rsasig, nss->sigalg, NULL) == SECSuccess);
96 /*@=moduncon =nullstate @*/
97 
98  return rc;
99 }
100 
101 static
102 int rpmnssSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
103  /*@modifies dig @*/
104 {
105  rpmnss nss = dig->impl;
106  int xx;
107 
108 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
109  xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 0);
110 
111  nss->sigalg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
112 
113  /* Compare leading 16 bits of digest for quick check. */
114  return memcmp(dig->sha1, sigp->signhash16, sizeof(sigp->signhash16));
115 }
116 
117 static
118 int rpmnssVerifyDSA(pgpDig dig)
119  /*@*/
120 {
121  rpmnss nss = dig->impl;
122  int rc;
123 
124  nss->item.type = siBuffer;
125  nss->item.data = dig->sha1;
126  nss->item.len = (unsigned) dig->sha1len;
127 
128 /*@-moduncon -nullstate @*/
129  rc = (VFY_VerifyDigest(&nss->item, nss->dsa, nss->dsasig, nss->sigalg, NULL) == SECSuccess);
130 /*@=moduncon =nullstate @*/
131 
132  return rc;
133 }
134 
135 static
136 int rpmnssSetECDSA(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
137  /*@*/
138 {
139  int rc = 1; /* XXX always fail. */
140  int xx;
141 
142 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
143  xx = rpmDigestFinal(ctx, (void **)NULL, NULL, 0);
144 
145  /* Compare leading 16 bits of digest for quick check. */
146 
147  return rc;
148 }
149 
150 static
151 int rpmnssVerifyECDSA(/*@unused@*/pgpDig dig)
152  /*@*/
153 {
154  int rc = 0; /* XXX always fail. */
155 
156  return rc;
157 }
158 
162 static
163 int rpmnssMpiSet(const char * pre, unsigned int lbits,
164  /*@out@*/ void * dest, const rpmuint8_t * p,
165  /*@null@*/ const rpmuint8_t * pend)
166  /*@modifies *dest @*/
167 {
168  unsigned int mbits = pgpMpiBits(p);
169  unsigned int nbits;
170  unsigned int nbytes;
171  char * t = dest;
172  unsigned int ix;
173 
174  if (pend != NULL && (p + ((mbits+7) >> 3)) > pend)
175  return 1;
176 
177  if (mbits > lbits)
178  return 1;
179 
180  nbits = (lbits > mbits ? lbits : mbits);
181  nbytes = ((nbits + 7) >> 3);
182  ix = ((nbits - mbits) >> 3);
183 
184 /*@-modfilesystem @*/
185 if (_pgp_debug)
186 fprintf(stderr, "*** mbits %u nbits %u nbytes %u ix %u\n", mbits, nbits, nbytes, ix);
187  if (ix > 0) memset(t, (int)'\0', ix);
188  memcpy(t+ix, p+2, nbytes-ix);
189 if (_pgp_debug && _pgp_print)
190 fprintf(stderr, "\t %s %s", pre, pgpHexStr(dest, nbytes));
191 /*@=modfilesystem @*/
192  return 0;
193 }
194 
198 static
199 /*@only@*/ /*@null@*/
200 SECItem * rpmnssMpiCopy(PRArenaPool * arena, /*@returned@*/ SECItem * item,
201  const rpmuint8_t * p)
202  /*@modifies item @*/
203 {
204  unsigned int nbytes = pgpMpiLen(p)-2;
205 
206 /*@-moduncon@*/
207  if (item == NULL) {
208  if ((item = SECITEM_AllocItem(arena, item, nbytes)) == NULL)
209  return item;
210  } else {
211  if (arena != NULL)
212  item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
213  else
214  item->data = PORT_Realloc(item->data, nbytes);
215 
216  if (item->data == NULL) {
217  if (arena == NULL)
218  SECITEM_FreeItem(item, PR_TRUE);
219  return NULL;
220  }
221  }
222 /*@=moduncon@*/
223 
224  memcpy(item->data, p+2, nbytes);
225  item->len = nbytes;
226 /*@-temptrans@*/
227  return item;
228 /*@=temptrans@*/
229 }
230 
231 static /*@null@*/
232 SECKEYPublicKey * rpmnssNewPublicKey(KeyType type)
233  /*@*/
234 {
235  PRArenaPool *arena;
236  SECKEYPublicKey *key;
237 
238 /*@-moduncon@*/
239  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
240  if (arena == NULL)
241  return NULL;
242 
243  key = PORT_ArenaZAlloc(arena, sizeof(*key));
244 
245  if (key == NULL) {
246  PORT_FreeArena(arena, PR_FALSE);
247  return NULL;
248  }
249 /*@=moduncon@*/
250 
251  key->keyType = type;
252  key->pkcs11ID = CK_INVALID_HANDLE;
253  key->pkcs11Slot = NULL;
254  key->arena = arena;
255 /*@-nullret@*/ /* key->pkcs11Slot can be NULL */
256  return key;
257 /*@=nullret@*/
258 }
259 
260 static
261 int rpmnssMpiItem(const char * pre, pgpDig dig, int itemno,
262  const rpmuint8_t * p, /*@null@*/ const rpmuint8_t * pend)
263  /*@*/
264 {
265  rpmnss nss = dig->impl;
266  int rc = 0;
267 
268 /*@-moduncon@*/
269  switch (itemno) {
270  default:
271 assert(0);
272  break;
273  case 10: /* RSA m**d */
274  nss->rsasig = rpmnssMpiCopy(NULL, nss->rsasig, p);
275  if (nss->rsasig == NULL)
276  rc = 1;
277  break;
278  case 20: /* DSA r */
279  nss->item.type = 0;
280  nss->item.len = 2 * (160/8);
281  nss->item.data = xcalloc(1, nss->item.len);
282  rc = rpmnssMpiSet(pre, 160, nss->item.data, p, pend);
283  break;
284  case 21: /* DSA s */
285  rc = rpmnssMpiSet(pre, 160, nss->item.data + (160/8), p, pend);
286  if (nss->dsasig != NULL)
287  SECITEM_FreeItem(nss->dsasig, PR_FALSE);
288  if ((nss->dsasig = SECITEM_AllocItem(NULL, NULL, 0)) == NULL
289  || DSAU_EncodeDerSig(nss->dsasig, &nss->item) != SECSuccess)
290  rc = 1;
291  nss->item.data = _free(nss->item.data);
292  break;
293  case 30: /* RSA n */
294  if (nss->rsa == NULL)
295  nss->rsa = rpmnssNewPublicKey(rsaKey);
296  if (nss->rsa == NULL)
297  rc = 1;
298  else
299  (void) rpmnssMpiCopy(nss->rsa->arena, &nss->rsa->u.rsa.modulus, p);
300  break;
301  case 31: /* RSA e */
302  if (nss->rsa == NULL)
303  nss->rsa = rpmnssNewPublicKey(rsaKey);
304  if (nss->rsa == NULL)
305  rc = 1;
306  else
307  (void) rpmnssMpiCopy(nss->rsa->arena, &nss->rsa->u.rsa.publicExponent, p);
308  break;
309  case 40: /* DSA p */
310  if (nss->dsa == NULL)
311  nss->dsa = rpmnssNewPublicKey(dsaKey);
312  if (nss->dsa == NULL)
313  rc = 1;
314  else
315  (void) rpmnssMpiCopy(nss->dsa->arena, &nss->dsa->u.dsa.params.prime, p);
316  break;
317  case 41: /* DSA q */
318  if (nss->dsa == NULL)
319  nss->dsa = rpmnssNewPublicKey(dsaKey);
320  if (nss->dsa == NULL)
321  rc = 1;
322  else
323  (void) rpmnssMpiCopy(nss->dsa->arena, &nss->dsa->u.dsa.params.subPrime, p);
324  break;
325  case 42: /* DSA g */
326  if (nss->dsa == NULL)
327  nss->dsa = rpmnssNewPublicKey(dsaKey);
328  if (nss->dsa == NULL)
329  rc = 1;
330  else
331  (void) rpmnssMpiCopy(nss->dsa->arena, &nss->dsa->u.dsa.params.base, p);
332  break;
333  case 43: /* DSA y */
334  if (nss->dsa == NULL)
335  nss->dsa = rpmnssNewPublicKey(dsaKey);
336  if (nss->dsa == NULL)
337  rc = 1;
338  else
339  (void) rpmnssMpiCopy(nss->dsa->arena, &nss->dsa->u.dsa.publicValue, p);
340  break;
341  }
342 /*@=moduncon@*/
343  return rc;
344 }
345 
346 /*@-mustmod@*/
347 static
348 void rpmnssClean(void * impl)
349  /*@modifies impl @*/
350 {
351  rpmnss nss = impl;
352 /*@-moduncon@*/
353  if (nss != NULL) {
354  if (nss->dsa != NULL) {
355  SECKEY_DestroyPublicKey(nss->dsa);
356  nss->dsa = NULL;
357  }
358  if (nss->dsasig != NULL) {
359  SECITEM_ZfreeItem(nss->dsasig, PR_TRUE);
360  nss->dsasig = NULL;
361  }
362  if (nss->rsa != NULL) {
363  SECKEY_DestroyPublicKey(nss->rsa);
364  nss->rsa = NULL;
365  }
366  if (nss->rsasig != NULL) {
367  SECITEM_ZfreeItem(nss->rsasig, PR_TRUE);
368  nss->rsasig = NULL;
369  }
370 /*@=moduncon@*/
371  }
372 }
373 /*@=mustmod@*/
374 
375 static /*@null@*/
376 void * rpmnssFree(/*@only@*/ void * impl)
377  /*@*/
378 {
379  rpmnss nss = impl;
380  if (nss != NULL) {
381  rpmnssClean(impl);
382  nss = _free(nss);
383  }
384  return NULL;
385 }
386 
387 static
388 void * rpmnssInit(void)
389  /*@globals _rpmnss_init @*/
390  /*@modifies _rpmnss_init @*/
391 {
392  rpmnss nss = xcalloc(1, sizeof(*nss));
393 
394 /*@-moduncon@*/
395  (void) NSS_NoDB_Init(NULL);
396 /*@=moduncon@*/
397  _rpmnss_init = 1;
398 
399  return (void *) nss;
400 }
401 
402 struct pgpImplVecs_s rpmnssImplVecs = {
403  rpmnssSetRSA, rpmnssVerifyRSA,
404  rpmnssSetDSA, rpmnssVerifyDSA,
405  rpmnssSetECDSA, rpmnssVerifyECDSA,
406  rpmnssMpiItem, rpmnssClean,
407  rpmnssFree, rpmnssInit
408 };
409 
410 #endif
411