~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/crypto/signature/ksign-parse.c

Version: ~ [ 2.4.21-47.EL ] ~ [ 2.6.9-67.EL ] ~ [ 2.6.18-128.el5 ] ~ [ 2.6.18-164.el5 ] ~ [ 2.6.18-194.el5 ] ~ [ 2.6.32-71.el6 ] ~
Architecture: ~ [ i386 ] ~ [ x86_64 ] ~

  1 /* parse-packet.c  - read packets
  2  * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
  3  *
  4  * This file is part of GnuPG.
  5  *
  6  * GnuPG is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License as published by
  8  * the Free Software Foundation; either version 2 of the License, or
  9  * (at your option) any later version.
 10  *
 11  * GnuPG is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  * GNU General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU General Public License
 17  * along with this program; if not, write to the Free Software
 18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 19  */
 20 
 21 #include <linux/kernel.h>
 22 #include <linux/slab.h>
 23 #include <asm/errno.h>
 24 #include "local.h"
 25 
 26 static inline uint32_t buffer_to_u32(const uint8_t *buffer)
 27 {
 28         uint32_t a;
 29         a =  *buffer << 24;
 30         a |= buffer[1] << 16;
 31         a |= buffer[2] << 8;
 32         a |= buffer[3];
 33         return a;
 34 }
 35 
 36 static inline uint16_t read_16(const uint8_t **datap)
 37 {
 38         uint16_t a;
 39         a = *(*datap)++ << 8;
 40         a |= *(*datap)++;
 41         return a;
 42 }
 43 
 44 static inline uint32_t read_32(const uint8_t **datap)
 45 {
 46         uint32_t a;
 47         a =  *(*datap)++ << 24;
 48         a |= *(*datap)++ << 16;
 49         a |= *(*datap)++ << 8;
 50         a |= *(*datap)++;
 51         return a;
 52 }
 53 
 54 void ksign_free_signature(struct ksign_signature *sig)
 55 {
 56         int i;
 57 
 58         if (!sig)
 59                 return;
 60 
 61         for (i = 0; i < DSA_NSIG; i++)
 62                 mpi_free(sig->data[i]);
 63         kfree(sig->hashed_data);
 64         kfree(sig->unhashed_data);
 65         kfree(sig);
 66 }
 67 
 68 void ksign_free_public_key(struct ksign_public_key *pk)
 69 {
 70         int i;
 71 
 72         if (pk) {
 73                 for (i = 0; i < DSA_NPKEY; i++)
 74                         mpi_free(pk->pkey[i]);
 75                 kfree(pk);
 76         }
 77 }
 78 
 79 void ksign_free_user_id(struct ksign_user_id *uid)
 80 {
 81         if (uid)
 82                 kfree(uid);
 83 }
 84 
 85 /*****************************************************************************/
 86 /*
 87  *
 88  */
 89 static void ksign_calc_pk_keyid(struct crypto_tfm *sha1,
 90                                 struct ksign_public_key *pk)
 91 {
 92         unsigned n;
 93         unsigned nb[DSA_NPKEY];
 94         unsigned nn[DSA_NPKEY];
 95         uint8_t *pp[DSA_NPKEY];
 96         uint32_t a32;
 97         int i;
 98         int npkey = DSA_NPKEY;
 99 
100         crypto_digest_init(sha1);
101 
102         n = pk->version < 4 ? 8 : 6;
103         for (i = 0; i < npkey; i++) {
104                 nb[i] = mpi_get_nbits(pk->pkey[i]);
105                 pp[i] = mpi_get_buffer( pk->pkey[i], nn + i, NULL);
106                 n += 2 + nn[i];
107         }
108 
109         SHA1_putc(sha1, 0x99);     /* ctb */
110         SHA1_putc(sha1, n >> 8);   /* 2 uint8_t length header */
111         SHA1_putc(sha1, n);
112 
113         if( pk->version < 4)
114                 SHA1_putc(sha1, 3);
115         else
116                 SHA1_putc(sha1, 4);
117 
118         a32 = pk->timestamp;
119         SHA1_putc(sha1, a32 >> 24 );
120         SHA1_putc(sha1, a32 >> 16 );
121         SHA1_putc(sha1, a32 >>  8 );
122         SHA1_putc(sha1, a32 >>  0 );
123 
124         if (pk->version < 4) {
125                 uint16_t a16;
126 
127                 if( pk->expiredate )
128                         a16 = (uint16_t) ((pk->expiredate - pk->timestamp) / 86400L);
129                 else
130                         a16 = 0;
131                 SHA1_putc(sha1, a16 >> 8);
132                 SHA1_putc(sha1, a16 >> 0);
133         }
134 
135         SHA1_putc(sha1, PUBKEY_ALGO_DSA);
136 
137         for (i = 0; i < npkey; i++) {
138                 SHA1_putc(sha1, nb[i] >> 8);
139                 SHA1_putc(sha1, nb[i]);
140                 SHA1_write(sha1, pp[i], nn[i]);
141                 kfree(pp[i]);
142         }
143 
144 } /* end ksign_calc_pk_keyid() */
145 
146 /*****************************************************************************/
147 /*
148  * parse a user ID embedded in a signature
149  */
150 static int ksign_parse_user_id(const uint8_t *datap, const uint8_t *endp,
151                                ksign_user_id_actor_t uidfnx, void *fnxdata)
152 {
153         struct ksign_user_id *uid;
154         int rc = 0;
155         int n;
156 
157         if (!uidfnx)
158                 return 0;
159 
160         n = endp - datap;
161         uid = kmalloc(sizeof(*uid) + n + 1, GFP_KERNEL);
162         if (!uid)
163                 return -ENOMEM;
164         uid->len = n;
165 
166         memcpy(uid->name, datap, n);
167         uid->name[n] = 0;
168 
169         rc = uidfnx(uid, fnxdata);
170         if (rc == 0)
171                 return rc; /* uidfnx keeps the record */
172         if (rc == 1)
173                 rc = 0;
174 
175         ksign_free_user_id(uid);
176         return rc;
177 } /* end ksign_parse_user_id() */
178 
179 /*****************************************************************************/
180 /*
181  * extract a public key embedded in a signature
182  */
183 static int ksign_parse_key(const uint8_t *datap, const uint8_t *endp,
184                            uint8_t *hdr, int hdrlen,
185                            ksign_public_key_actor_t pkfnx, void *fnxdata)
186 {
187         struct ksign_public_key *pk;
188         struct crypto_tfm *sha1_tfm;
189         unsigned long timestamp, expiredate;
190         uint8_t sha1[SHA1_DIGEST_SIZE];
191         int i, version;
192         int is_v4 = 0;
193         int rc = 0;
194 
195         if (endp - datap < 12) {
196                 printk("ksign: public key packet too short\n");
197                 return -EBADMSG;
198         }
199 
200         version = *datap++;
201         switch (version) {
202         case 4:
203                 is_v4 = 1;
204         case 2:
205         case 3:
206                 break;
207         default:
208                 printk("ksign: public key packet with unknown version %d\n",
209                        version);
210                 return -EBADMSG;
211         }
212 
213         timestamp = read_32(&datap);
214         if (is_v4)
215                 expiredate = 0; /* have to get it from the selfsignature */
216         else {
217                 unsigned short ndays;
218                 ndays = read_16(&datap);
219                 if (ndays)
220                         expiredate = timestamp + ndays * 86400L;
221                 else
222                         expiredate = 0;
223         }
224 
225         if (*datap++ != PUBKEY_ALGO_DSA) {
226                 printk("ksign: public key packet with unknown version %d\n",
227                        version);
228                 return 0;
229         }
230 
231         /* extract the stuff from the DSA public key */
232         pk = kmalloc(sizeof(struct ksign_public_key), GFP_KERNEL);
233         if (!pk)
234                 return -ENOMEM;
235 
236         memset(pk, 0, sizeof(struct ksign_public_key));
237         atomic_set(&pk->count, 1);
238         pk->timestamp   = timestamp;
239         pk->expiredate  = expiredate;
240         pk->hdrbytes    = hdrlen;
241         pk->version     = version;
242 
243         for (i = 0; i < DSA_NPKEY; i++) {
244                 unsigned int remaining = endp - datap;
245                 pk->pkey[i] = mpi_read_from_buffer(datap, &remaining);
246                 datap += remaining;
247         }
248 
249         rc = -ENOMEM;
250 
251         sha1_tfm = crypto_alloc_tfm2("sha1", 0, 1);
252         if (!sha1_tfm)
253                 goto cleanup;
254 
255         ksign_calc_pk_keyid(sha1_tfm, pk);
256         crypto_digest_final(sha1_tfm, sha1);
257         crypto_free_tfm(sha1_tfm);
258 
259         pk->keyid[0] = sha1[12] << 24 | sha1[13] << 16 | sha1[14] << 8 | sha1[15];
260         pk->keyid[1] = sha1[16] << 24 | sha1[17] << 16 | sha1[18] << 8 | sha1[19];
261 
262         rc = 0;
263         if (pkfnx)
264                 rc = pkfnx(pk, fnxdata);
265 
266  cleanup:
267         ksign_put_public_key(pk);
268         return rc;
269 } /* end ksign_parse_key() */
270 
271 /*****************************************************************************/
272 /*
273  *
274  */
275 static const uint8_t *ksign_find_sig_issuer(const uint8_t *buffer)
276 {
277         size_t buflen;
278         size_t n;
279         int type;
280         int seq = 0;
281 
282         if (!buffer)
283                 return NULL;
284 
285         buflen = read_16(&buffer);
286         while (buflen) {
287                 n = *buffer++; buflen--;
288                 if (n == 255) {
289                         if (buflen < 4)
290                                 goto too_short;
291                         n = read_32(&buffer);
292                         buflen -= 4;
293                 }
294                 else if (n >= 192) {
295                         if(buflen < 2)
296                                 goto too_short;
297                         n = ((n - 192) << 8) + *buffer + 192;
298                         buffer++;
299                         buflen--;
300                 }
301 
302                 if (buflen < n)
303                         goto too_short;
304 
305                 type = *buffer & 0x7f;
306                 if (!(++seq > 0))
307                         ;
308                 else if (type == SIGSUBPKT_ISSUER) { /* found */
309                         buffer++;
310                         n--;
311                         if (n > buflen || n < 8)
312                                 goto too_short;
313                         return buffer;
314                 }
315 
316                 buffer += n;
317                 buflen -= n;
318         }
319 
320  too_short:
321         return NULL; /* end of subpackets; not found */
322 } /* end ksign_find_sig_issuer() */
323 
324 /*****************************************************************************/
325 /*
326  * extract signature data embedded in a signature
327  */
328 static int ksign_parse_signature(const uint8_t *datap, const uint8_t *endp,
329                                  ksign_signature_actor_t sigfnx, void *fnxdata)
330 {
331         struct ksign_signature *sig;
332         size_t n;
333         int version, is_v4 = 0;
334         int rc;
335         int i;
336 
337         if (endp - datap < 16) {
338                 printk("ksign: signature packet too short\n");
339                 return -EBADMSG;
340         }
341 
342         version = *datap++;
343         switch (version) {
344         case 4:
345                 is_v4 = 1;
346         case 3:
347         case 2:
348                 break;
349         default:
350                 printk("ksign: signature packet with unknown version %d\n", version);
351                 return 0;
352         }
353 
354         /* store information */
355         sig = kmalloc(sizeof(*sig), GFP_KERNEL);
356         if (!sig)
357                 return -ENOMEM;
358 
359         memset(sig, 0, sizeof(*sig));
360         sig->version = version;
361 
362         if (!is_v4)
363                 datap++; /* ignore md5 length */
364 
365         sig->sig_class = *datap++;
366         if (!is_v4) {
367                 sig->timestamp = read_32(&datap);
368                 sig->keyid[0] = read_32(&datap);
369                 sig->keyid[1] = read_32(&datap);
370         }
371 
372         rc = 0;
373         if (*datap++ != PUBKEY_ALGO_DSA) {
374                 printk("ksign: ignoring non-DSA signature\n");
375                 goto leave;
376         }
377         if (*datap++ != DIGEST_ALGO_SHA1) {
378                 printk("ksign: ignoring non-SHA1 signature\n");
379                 goto leave;
380         }
381 
382         rc = -EBADMSG;
383         if (is_v4) { /* read subpackets */
384                 n = read_16(&datap); /* length of hashed data */
385                 if (n > 10000) {
386                         printk("ksign: signature packet: hashed data too long\n");
387                         goto leave;
388                 }
389                 if (n) {
390                         if ((size_t)(endp - datap) < n) {
391                                 printk("ksign: signature packet: available data too short\n");
392                                 goto leave;
393                         }
394                         sig->hashed_data = kmalloc(n + 2, GFP_KERNEL);
395                         if (!sig->hashed_data) {
396                                 rc = -ENOMEM;
397                                 goto leave;
398                         }
399                         sig->hashed_data[0] = n >> 8;
400                         sig->hashed_data[1] = n;
401                         memcpy(sig->hashed_data + 2, datap, n);
402                         datap += n;
403                 }
404 
405                 n = read_16(&datap); /* length of unhashed data */
406                 if (n > 10000) {
407                         printk("ksign: signature packet: unhashed data too long\n");
408                         goto leave;
409                 }
410                 if (n) {
411                         if ((size_t) (endp - datap) < n) {
412                                 printk("ksign: signature packet: available data too short\n");
413                                 goto leave;
414                         }
415                         sig->unhashed_data = kmalloc(n + 2, GFP_KERNEL);
416                         if (!sig->unhashed_data) {
417                                 rc = -ENOMEM;
418                                 goto leave;
419                         }
420                         sig->unhashed_data[0] = n >> 8;
421                         sig->unhashed_data[1] = n;
422                         memcpy(sig->unhashed_data + 2, datap, n);
423                         datap += n;
424                 }
425         }
426 
427         if (endp - datap < 5) { /* sanity check */
428                 printk("ksign: signature packet too short\n");
429                 goto leave;
430         }
431 
432         sig->digest_start[0] = *datap++;
433         sig->digest_start[1] = *datap++;
434 
435         if (is_v4) {
436                 const uint8_t *p;
437 
438                 p = ksign_find_sig_issuer(sig->hashed_data);
439                 if (!p)
440                         p = ksign_find_sig_issuer(sig->unhashed_data);
441                 if (!p)
442                         printk("ksign: signature packet without issuer\n");
443                 else {
444                         sig->keyid[0] = buffer_to_u32(p);
445                         sig->keyid[1] = buffer_to_u32(p + 4);
446                 }
447         }
448 
449         for (i = 0; i < DSA_NSIG; i++) {
450                 unsigned remaining = endp - datap;
451                 sig->data[i] = mpi_read_from_buffer(datap, &remaining);
452                 datap += remaining;
453         }
454 
455         rc = 0;
456         if (sigfnx) {
457                 rc = sigfnx(sig, fnxdata);
458                 if (rc == 0)
459                         return rc; /* sigfnx keeps the signature */
460                 if (rc == 1)
461                         rc = 0;
462         }
463 
464  leave:
465         ksign_free_signature(sig);
466         return rc;
467 } /* end ksign_parse_signature() */
468 
469 /*****************************************************************************/
470 /*
471  * parse the next packet and call appropriate handler function for known types
472  * - returns:
473  *     0 on EOF
474  *     1 if there might be more packets
475  *     -EBADMSG if the packet is in an invalid format
476  *     -ve on other error
477  */
478 static int ksign_parse_one_packet(const uint8_t **datap,
479                                   const uint8_t *endp,
480                                   ksign_signature_actor_t sigfnx,
481                                   ksign_public_key_actor_t pkfnx,
482                                   ksign_user_id_actor_t uidfnx,
483                                   void *data)
484 {
485         int rc, c, ctb, pkttype, lenuint8_ts;
486         unsigned long pktlen;
487         uint8_t hdr[8];
488         int hdrlen;
489 
490         /* extract the next packet and dispatch it */
491         rc = 0;
492         if (*datap >= endp)
493                 goto leave;
494         ctb = *(*datap)++;
495 
496         rc = -EBADMSG;
497 
498         hdrlen = 0;
499         hdr[hdrlen++] = ctb;
500         if (!(ctb & 0x80)) {
501                 printk("ksign: invalid packet (ctb=%02x)\n", ctb);
502                 goto leave;
503         }
504 
505         pktlen = 0;
506         if (ctb & 0x40) {
507                 pkttype = ctb & 0x3f;
508                 if (*datap >= endp) {
509                         printk("ksign: 1st length byte missing\n");
510                         goto leave;
511                 }
512                 c = *(*datap)++;
513                 hdr[hdrlen++] = c;
514 
515                 if (c < 192) {
516                         pktlen = c;
517                 }
518                 else if (c < 224) {
519                         pktlen = (c - 192) * 256;
520                         if (*datap >= endp) {
521                                 printk("ksign: 2nd length uint8_t missing\n");
522                                 goto leave;
523                         }
524                         c = *(*datap)++;
525                         hdr[hdrlen++] = c;
526                         pktlen += c + 192;
527                 }
528                 else if (c == 255) {
529                         if (*datap + 3 >= endp) {
530                                 printk("ksign: 4 uint8_t length invalid\n");
531                                 goto leave;
532                         }
533                         pktlen  = (hdr[hdrlen++] = *(*datap)++ << 24    );
534                         pktlen |= (hdr[hdrlen++] = *(*datap)++ << 16    );
535                         pktlen |= (hdr[hdrlen++] = *(*datap)++ <<  8    );
536                         pktlen |= (hdr[hdrlen++] = *(*datap)++ <<  0    );
537                 }
538                 else {
539                         pktlen = 0;/* to indicate partial length */
540                 }
541         }
542         else {
543                 pkttype = (ctb >> 2) & 0xf;
544                 lenuint8_ts = ((ctb & 3) == 3) ? 0 : (1 << (ctb & 3));
545                 if( !lenuint8_ts ) {
546                         pktlen = 0; /* don't know the value */
547                 }
548                 else {
549                         if (*datap + lenuint8_ts > endp) {
550                                 printk("ksign: length uint8_ts missing\n");
551                                 goto leave;
552                         }
553                         for( ; lenuint8_ts; lenuint8_ts-- ) {
554                                 pktlen <<= 8;
555                                 pktlen |= hdr[hdrlen++] = *(*datap)++;
556                         }
557                 }
558         }
559 
560         if (*datap + pktlen > endp) {
561                 printk("ksign: packet length longer than available data\n");
562                 goto leave;
563         }
564 
565         /* deal with the next packet appropriately */
566         switch (pkttype) {
567         case PKT_PUBLIC_KEY:
568                 rc = ksign_parse_key(*datap, *datap + pktlen, hdr, hdrlen, pkfnx, data);
569                 break;
570         case PKT_SIGNATURE:
571                 rc = ksign_parse_signature(*datap, *datap + pktlen, sigfnx, data);
572                 break;
573         case PKT_USER_ID:
574                 rc = ksign_parse_user_id(*datap, *datap + pktlen, uidfnx, data);
575                 break;
576         default:
577                 rc = 0; /* unknown packet */
578                 break;
579         }
580 
581         *datap += pktlen;
582  leave:
583         return rc;
584 } /* end ksign_parse_one_packet() */
585 
586 /*****************************************************************************/
587 /*
588  * parse the contents of a packet buffer, passing the signature, public key and
589  * user ID to the caller's callback functions
590  */
591 int ksign_parse_packets(const uint8_t *buf,
592                         size_t size,
593                         ksign_signature_actor_t sigfnx,
594                         ksign_public_key_actor_t pkfnx,
595                         ksign_user_id_actor_t uidfnx,
596                         void *data)
597 {
598         const uint8_t *datap, *endp;
599         int rc;
600 
601         datap = buf;
602         endp = buf + size;
603         do {
604                 rc = ksign_parse_one_packet(&datap, endp,
605                                             sigfnx, pkfnx, uidfnx, data);
606         } while (rc == 0 && datap < endp);
607 
608         return rc;
609 } /* end ksign_parse_packets() */
610 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.