rpm  5.2.1
rpmssl.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 #include <rpmlog.h>
7 
8 #include <rpmiotypes.h>
9 #define _RPMPGP_INTERNAL
10 #if defined(WITH_SSL)
11 
12 #if defined(__LCLINT__) && !defined(__i386__)
13 #define __i386__
14 #endif
15 
16 #define _RPMSSL_INTERNAL
17 #include <rpmssl.h>
18 #endif
19 
20 #include "debug.h"
21 
22 #if defined(WITH_SSL)
23 
24 /*@access pgpDig @*/
25 /*@access pgpDigParams @*/
26 
27 /*@-redecl@*/
28 /*@unchecked@*/
29 extern int _pgp_debug;
30 
31 /*@unchecked@*/
32 extern int _pgp_print;
33 /*@=redecl@*/
34 
40 static
41 unsigned char nibble(char c)
42  /*@*/
43 {
44  if (c >= '0' && c <= '9')
45  return (unsigned char) (c - '0');
46  if (c >= 'A' && c <= 'F')
47  return (unsigned char)((int)(c - 'A') + 10);
48  if (c >= 'a' && c <= 'f')
49  return (unsigned char)((int)(c - 'a') + 10);
50  return (unsigned char) '\0';
51 }
52 
53 /*@-modfilesys@*/
54 static
55 void hexdump(const char * msg, unsigned char * b, size_t blen)
56  /*@*/
57 {
58  static const char hex[] = "0123456789abcdef";
59 
60  fprintf(stderr, "*** %s:", msg);
61  if (b != NULL)
62  while (blen > 0) {
63  fprintf(stderr, "%c%c",
64  hex[ (unsigned)((*b >> 4) & 0x0f) ],
65  hex[ (unsigned)((*b ) & 0x0f) ]);
66  blen--;
67  b++;
68  }
69  fprintf(stderr, "\n");
70  return;
71 }
72 /*@=modfilesys@*/
73 
74 static
75 int rpmsslSetRSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
76  /*@modifies dig @*/
77 {
78  rpmssl ssl = dig->impl;
79  unsigned int nbits = BN_num_bits(ssl->c);
80  unsigned int nb = (nbits + 7) >> 3;
81  const char * prefix = rpmDigestASN1(ctx);
82  const char * hexstr;
83  const char * s;
84  rpmuint8_t signhash16[2];
85  char * tt;
86  int xx;
87 
88 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
89  if (prefix == NULL)
90  return 1;
91 
92  xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 1);
93  hexstr = tt = xmalloc(2 * nb + 1);
94  memset(tt, (int) 'f', (2 * nb));
95  tt[0] = '0'; tt[1] = '0';
96  tt[2] = '0'; tt[3] = '1';
97  tt += (2 * nb) - strlen(prefix) - strlen(dig->md5) - 2;
98  *tt++ = '0'; *tt++ = '0';
99  tt = stpcpy(tt, prefix);
100  tt = stpcpy(tt, dig->md5);
101 
102  /* Set RSA hash. */
103 /*@-moduncon -noeffectuncon @*/
104  xx = BN_hex2bn(&ssl->rsahm, hexstr);
105 /*@=moduncon =noeffectuncon @*/
106 
107 /*@-modfilesys@*/
108 if (_pgp_debug < 0) fprintf(stderr, "*** rsahm: %s\n", hexstr);
109  hexstr = _free(hexstr);
110 /*@=modfilesys@*/
111 
112  /* Compare leading 16 bits of digest for quick check. */
113  s = dig->md5;
114 /*@-type@*/
115  signhash16[0] = (rpmuint8_t) (nibble(s[0]) << 4) | nibble(s[1]);
116  signhash16[1] = (rpmuint8_t) (nibble(s[2]) << 4) | nibble(s[3]);
117 /*@=type@*/
118  return memcmp(signhash16, sigp->signhash16, sizeof(sigp->signhash16));
119 }
120 
121 static unsigned char * rpmsslBN2bin(const char * msg, const BIGNUM * s, size_t maxn)
122 {
123  unsigned char * t = xcalloc(1, maxn);
124 /*@-modunconnomods@*/
125  size_t nt = BN_bn2bin(s, t);
126 /*@=modunconnomods@*/
127 
128  if (nt < maxn) {
129  size_t pad = (maxn - nt);
130 /*@-modfilesys@*/
131 if (_pgp_debug < 0) fprintf(stderr, "\tmemmove(%p, %p, %u)\n", t+pad, t, (unsigned)nt);
132 /*@=modfilesys@*/
133  memmove(t+pad, t, nt);
134 /*@-modfilesys@*/
135 if (_pgp_debug < 0) fprintf(stderr, "\tmemset(%p, 0, %u)\n", t, (unsigned)pad);
136 /*@=modfilesys@*/
137  memset(t, 0, pad);
138  }
139 /*@-modfilesys@*/
140 if (_pgp_debug < 0) hexdump(msg, t, maxn);
141 /*@=modfilesys@*/
142  return t;
143 }
144 
145 static
146 int rpmsslVerifyRSA(pgpDig dig)
147  /*@*/
148 {
149  rpmssl ssl = dig->impl;
150 /*@-moduncon@*/
151  size_t maxn = BN_num_bytes(ssl->rsa->n);
152  unsigned char * hm = rpmsslBN2bin("hm", ssl->rsahm, maxn);
153  unsigned char * c = rpmsslBN2bin(" c", ssl->c, maxn);
154  size_t nb = RSA_public_decrypt((int)maxn, c, c, ssl->rsa, RSA_PKCS1_PADDING);
155 /*@=moduncon@*/
156  size_t i;
157  int rc = 0;
158  int xx;
159 
160  /* Verify RSA signature. */
161  /* XXX This is _NOT_ the correct openssl function to use:
162  * rc = RSA_verify(type, m, m_len, sigbuf, siglen, ssl->rsa)
163  *
164  * Here's what needs doing (from OpenPGP reference sources in 1999):
165  * static u32_t checkrsa(BIGNUM * a, RSA * key, u8_t * hash, int hlen)
166  * {
167  * u8_t dbuf[MAXSIGM];
168  * int j, ll;
169  *
170  * j = BN_bn2bin(a, dbuf);
171  * ll = BN_num_bytes(key->n);
172  * while (j < ll)
173  * memmove(&dbuf[1], dbuf, j++), dbuf[0] = 0;
174  * j = RSA_public_decrypt(ll, dbuf, dbuf, key, RSA_PKCS1_PADDING);
175  * RSA_free(key);
176  * return (j != hlen || memcmp(dbuf, hash, j));
177  * }
178  */
179  for (i = 2; i < maxn; i++) {
180  if (hm[i] == 0xff)
181  continue;
182  i++;
183 /*@-modfilesys@*/
184 if (_pgp_debug < 0) hexdump("HM", hm + i, (maxn - i));
185 /*@=modfilesys@*/
186  break;
187  }
188 
189 /*@-modfilesys@*/
190 if (_pgp_debug < 0) hexdump("HM", hm + (maxn - nb), nb);
191 if (_pgp_debug < 0) hexdump(" C", c, nb);
192 /*@=modfilesys@*/
193 
194  rc = ((maxn - i) == nb && (xx = memcmp(hm+i, c, nb)) == 0);
195 
196  c = _free(c);
197  hm = _free(hm);
198 
199  return rc;
200 }
201 
202 static
203 int rpmsslSetDSA(/*@only@*/ DIGEST_CTX ctx, pgpDig dig, pgpDigParams sigp)
204  /*@modifies dig @*/
205 {
206  int xx;
207 
208 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
209  /* Set DSA hash. */
210  xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 0);
211 
212  /* Compare leading 16 bits of digest for quick check. */
213  return memcmp(dig->sha1, sigp->signhash16, sizeof(sigp->signhash16));
214 }
215 
216 static
217 int rpmsslVerifyDSA(pgpDig dig)
218  /*@*/
219 {
220  rpmssl ssl = dig->impl;
221  int rc;
222 
223  /* Verify DSA signature. */
224 /*@-moduncon@*/
225  rc = (DSA_do_verify(dig->sha1, (int)dig->sha1len, ssl->dsasig, ssl->dsa) == 1);
226 /*@=moduncon@*/
227 
228  return rc;
229 }
230 
231 
232 static
233 int rpmsslSetECDSA(/*@only@*/ DIGEST_CTX ctx, /*@unused@*/pgpDig dig, pgpDigParams sigp)
234  /*@*/
235 {
236  int rc = 1; /* XXX always fail. */
237  int xx;
238 
239 assert(sigp->hash_algo == rpmDigestAlgo(ctx));
240  xx = rpmDigestFinal(ctx, (void **)NULL, NULL, 0);
241 
242  /* Compare leading 16 bits of digest for quick check. */
243 
244  return rc;
245 }
246 
247 static
248 int rpmsslVerifyECDSA(/*@unused@*/pgpDig dig)
249  /*@*/
250 {
251  int rc = 0; /* XXX always fail. */
252 
253  return rc;
254 }
255 
256 static
257 int rpmsslMpiItem(/*@unused@*/ const char * pre, pgpDig dig, int itemno,
258  const rpmuint8_t * p,
259  /*@unused@*/ /*@null@*/ const rpmuint8_t * pend)
260  /*@*/
261 {
262  rpmssl ssl = dig->impl;
263  unsigned int nb = ((pgpMpiBits(p) + 7) >> 3);
264  int rc = 0;
265 
266 /*@-moduncon@*/
267  switch (itemno) {
268  default:
269 assert(0);
270  break;
271  case 10: /* RSA m**d */
272  ssl->c = BN_bin2bn(p+2, nb, ssl->c);
273  break;
274  case 20: /* DSA r */
275  if (ssl->dsasig == NULL) ssl->dsasig = DSA_SIG_new();
276  ssl->dsasig->r = BN_bin2bn(p+2, nb, ssl->dsasig->r);
277  break;
278  case 21: /* DSA s */
279  if (ssl->dsasig == NULL) ssl->dsasig = DSA_SIG_new();
280  ssl->dsasig->s = BN_bin2bn(p+2, nb, ssl->dsasig->s);
281  break;
282  case 30: /* RSA n */
283  if (ssl->rsa == NULL) ssl->rsa = RSA_new();
284  ssl->rsa->n = BN_bin2bn(p+2, nb, ssl->rsa->n);
285  break;
286  case 31: /* RSA e */
287  if (ssl->rsa == NULL) ssl->rsa = RSA_new();
288  ssl->rsa->e = BN_bin2bn(p+2, nb, ssl->rsa->e);
289  break;
290  case 40: /* DSA p */
291  if (ssl->dsa == NULL) ssl->dsa = DSA_new();
292  ssl->dsa->p = BN_bin2bn(p+2, nb, ssl->dsa->p);
293  break;
294  case 41: /* DSA q */
295  if (ssl->dsa == NULL) ssl->dsa = DSA_new();
296  ssl->dsa->q = BN_bin2bn(p+2, nb, ssl->dsa->q);
297  break;
298  case 42: /* DSA g */
299  if (ssl->dsa == NULL) ssl->dsa = DSA_new();
300  ssl->dsa->g = BN_bin2bn(p+2, nb, ssl->dsa->g);
301  break;
302  case 43: /* DSA y */
303  if (ssl->dsa == NULL) ssl->dsa = DSA_new();
304  ssl->dsa->pub_key = BN_bin2bn(p+2, nb, ssl->dsa->pub_key);
305  break;
306  }
307 /*@=moduncon@*/
308  return rc;
309 }
310 
311 /*@-mustmod@*/
312 static
313 void rpmsslClean(void * impl)
314  /*@modifies impl @*/
315 {
316  rpmssl ssl = impl;
317 /*@-moduncon@*/
318  if (ssl != NULL) {
319  if (ssl->dsa) {
320  DSA_free(ssl->dsa);
321  ssl->dsa = NULL;
322  }
323  if (ssl->dsasig) {
324  DSA_SIG_free(ssl->dsasig);
325  ssl->dsasig = NULL;
326  }
327  if (ssl->rsa) {
328  RSA_free(ssl->rsa);
329  ssl->rsa = NULL;
330  }
331  if (ssl->c) {
332  BN_free(ssl->c);
333  ssl->c = NULL;
334  }
335  }
336 /*@=moduncon@*/
337 }
338 /*@=mustmod@*/
339 
340 static /*@null@*/
341 void * rpmsslFree(/*@only@*/ void * impl)
342  /*@modifies impl @*/
343 {
344  rpmssl ssl = impl;
345  rpmsslClean(impl);
346  ssl = _free(ssl);
347  return NULL;
348 }
349 
350 static
351 void * rpmsslInit(void)
352  /*@*/
353 {
354  rpmssl ssl = xcalloc(1, sizeof(*ssl));
355 /*@-moduncon@*/
356  ERR_load_crypto_strings();
357 /*@=moduncon@*/
358  return (void *) ssl;
359 }
360 
361 struct pgpImplVecs_s rpmsslImplVecs = {
362  rpmsslSetRSA, rpmsslVerifyRSA,
363  rpmsslSetDSA, rpmsslVerifyDSA,
364  rpmsslSetECDSA, rpmsslVerifyECDSA,
365  rpmsslMpiItem, rpmsslClean,
366  rpmsslFree, rpmsslInit
367 };
368 
369 #endif
370