1 /* parse-packet.c - read packets
2 * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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
21 #include <linux/kernel.h>
22 #include <linux/slab.h>
23 #include <asm/errno.h>
26 static inline uint32_t buffer_to_u32(const uint8_t *buffer)
36 static inline uint16_t read_16(const uint8_t **datap)
44 static inline uint32_t read_32(const uint8_t **datap)
47 a = *(*datap)++ << 24;
48 a |= *(*datap)++ << 16;
49 a |= *(*datap)++ << 8;
54 void ksign_free_signature(struct ksign_signature *sig)
61 for (i = 0; i < DSA_NSIG; i++)
62 mpi_free(sig->data[i]);
63 kfree(sig->hashed_data);
64 kfree(sig->unhashed_data);
68 void ksign_free_public_key(struct ksign_public_key *pk)
73 for (i = 0; i < DSA_NPKEY; i++)
74 mpi_free(pk->pkey[i]);
79 void ksign_free_user_id(struct ksign_user_id *uid)
85 /*****************************************************************************/
89 static void ksign_calc_pk_keyid(struct crypto_tfm *sha1,
90 struct ksign_public_key *pk)
93 unsigned nb[DSA_NPKEY];
94 unsigned nn[DSA_NPKEY];
95 uint8_t *pp[DSA_NPKEY];
98 int npkey = DSA_NPKEY;
100 crypto_digest_init(sha1);
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);
109 SHA1_putc(sha1, 0x99); /* ctb */
110 SHA1_putc(sha1, n >> 8); /* 2 uint8_t length header */
119 SHA1_putc(sha1, a32 >> 24 );
120 SHA1_putc(sha1, a32 >> 16 );
121 SHA1_putc(sha1, a32 >> 8 );
122 SHA1_putc(sha1, a32 >> 0 );
124 if (pk->version < 4) {
128 a16 = (uint16_t) ((pk->expiredate - pk->timestamp) / 86400L);
131 SHA1_putc(sha1, a16 >> 8);
132 SHA1_putc(sha1, a16 >> 0);
135 SHA1_putc(sha1, PUBKEY_ALGO_DSA);
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]);
144 } /* end ksign_calc_pk_keyid() */
146 /*****************************************************************************/
148 * parse a user ID embedded in a signature
150 static int ksign_parse_user_id(const uint8_t *datap, const uint8_t *endp,
151 ksign_user_id_actor_t uidfnx, void *fnxdata)
153 struct ksign_user_id *uid;
161 uid = kmalloc(sizeof(*uid) + n + 1, GFP_KERNEL);
166 memcpy(uid->name, datap, n);
169 rc = uidfnx(uid, fnxdata);
171 return rc; /* uidfnx keeps the record */
175 ksign_free_user_id(uid);
177 } /* end ksign_parse_user_id() */
179 /*****************************************************************************/
181 * extract a public key embedded in a signature
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)
187 struct ksign_public_key *pk;
188 struct crypto_tfm *sha1_tfm;
189 unsigned long timestamp, expiredate;
190 uint8_t sha1[SHA1_DIGEST_SIZE];
195 if (endp - datap < 12) {
196 printk("ksign: public key packet too short\n");
208 printk("ksign: public key packet with unknown version %d\n",
213 timestamp = read_32(&datap);
215 expiredate = 0; /* have to get it from the selfsignature */
217 unsigned short ndays;
218 ndays = read_16(&datap);
220 expiredate = timestamp + ndays * 86400L;
225 if (*datap++ != PUBKEY_ALGO_DSA) {
226 printk("ksign: public key packet with unknown version %d\n",
231 /* extract the stuff from the DSA public key */
232 pk = kmalloc(sizeof(struct ksign_public_key), GFP_KERNEL);
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;
243 for (i = 0; i < DSA_NPKEY; i++) {
244 unsigned int remaining = endp - datap;
245 pk->pkey[i] = mpi_read_from_buffer(datap, &remaining);
251 sha1_tfm = crypto_alloc_tfm2("sha1", 0, 1);
255 ksign_calc_pk_keyid(sha1_tfm, pk);
256 crypto_digest_final(sha1_tfm, sha1);
257 crypto_free_tfm(sha1_tfm);
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];
264 rc = pkfnx(pk, fnxdata);
267 ksign_put_public_key(pk);
269 } /* end ksign_parse_key() */
271 /*****************************************************************************/
275 static const uint8_t *ksign_find_sig_issuer(const uint8_t *buffer)
285 buflen = read_16(&buffer);
287 n = *buffer++; buflen--;
291 n = read_32(&buffer);
297 n = ((n - 192) << 8) + *buffer + 192;
305 type = *buffer & 0x7f;
308 else if (type == SIGSUBPKT_ISSUER) { /* found */
311 if (n > buflen || n < 8)
321 return NULL; /* end of subpackets; not found */
322 } /* end ksign_find_sig_issuer() */
324 /*****************************************************************************/
326 * extract signature data embedded in a signature
328 static int ksign_parse_signature(const uint8_t *datap, const uint8_t *endp,
329 ksign_signature_actor_t sigfnx, void *fnxdata)
331 struct ksign_signature *sig;
333 int version, is_v4 = 0;
337 if (endp - datap < 16) {
338 printk("ksign: signature packet too short\n");
350 printk("ksign: signature packet with unknown version %d\n", version);
354 /* store information */
355 sig = kmalloc(sizeof(*sig), GFP_KERNEL);
359 memset(sig, 0, sizeof(*sig));
360 sig->version = version;
363 datap++; /* ignore md5 length */
365 sig->sig_class = *datap++;
367 sig->timestamp = read_32(&datap);
368 sig->keyid[0] = read_32(&datap);
369 sig->keyid[1] = read_32(&datap);
373 if (*datap++ != PUBKEY_ALGO_DSA) {
374 printk("ksign: ignoring non-DSA signature\n");
377 if (*datap++ != DIGEST_ALGO_SHA1) {
378 printk("ksign: ignoring non-SHA1 signature\n");
383 if (is_v4) { /* read subpackets */
384 n = read_16(&datap); /* length of hashed data */
386 printk("ksign: signature packet: hashed data too long\n");
390 if ((size_t)(endp - datap) < n) {
391 printk("ksign: signature packet: available data too short\n");
394 sig->hashed_data = kmalloc(n + 2, GFP_KERNEL);
395 if (!sig->hashed_data) {
399 sig->hashed_data[0] = n >> 8;
400 sig->hashed_data[1] = n;
401 memcpy(sig->hashed_data + 2, datap, n);
405 n = read_16(&datap); /* length of unhashed data */
407 printk("ksign: signature packet: unhashed data too long\n");
411 if ((size_t) (endp - datap) < n) {
412 printk("ksign: signature packet: available data too short\n");
415 sig->unhashed_data = kmalloc(n + 2, GFP_KERNEL);
416 if (!sig->unhashed_data) {
420 sig->unhashed_data[0] = n >> 8;
421 sig->unhashed_data[1] = n;
422 memcpy(sig->unhashed_data + 2, datap, n);
427 if (endp - datap < 5) { /* sanity check */
428 printk("ksign: signature packet too short\n");
432 sig->digest_start[0] = *datap++;
433 sig->digest_start[1] = *datap++;
438 p = ksign_find_sig_issuer(sig->hashed_data);
440 p = ksign_find_sig_issuer(sig->unhashed_data);
442 printk("ksign: signature packet without issuer\n");
444 sig->keyid[0] = buffer_to_u32(p);
445 sig->keyid[1] = buffer_to_u32(p + 4);
449 for (i = 0; i < DSA_NSIG; i++) {
450 unsigned remaining = endp - datap;
451 sig->data[i] = mpi_read_from_buffer(datap, &remaining);
457 rc = sigfnx(sig, fnxdata);
459 return rc; /* sigfnx keeps the signature */
465 ksign_free_signature(sig);
467 } /* end ksign_parse_signature() */
469 /*****************************************************************************/
471 * parse the next packet and call appropriate handler function for known types
474 * 1 if there might be more packets
475 * -EBADMSG if the packet is in an invalid format
478 static int ksign_parse_one_packet(const uint8_t **datap,
480 ksign_signature_actor_t sigfnx,
481 ksign_public_key_actor_t pkfnx,
482 ksign_user_id_actor_t uidfnx,
485 int rc, c, ctb, pkttype, lenuint8_ts;
486 unsigned long pktlen;
490 /* extract the next packet and dispatch it */
501 printk("ksign: invalid packet (ctb=%02x)\n", ctb);
507 pkttype = ctb & 0x3f;
508 if (*datap >= endp) {
509 printk("ksign: 1st length byte missing\n");
519 pktlen = (c - 192) * 256;
520 if (*datap >= endp) {
521 printk("ksign: 2nd length uint8_t missing\n");
529 if (*datap + 3 >= endp) {
530 printk("ksign: 4 uint8_t length invalid\n");
533 pktlen = (hdr[hdrlen++] = *(*datap)++ << 24 );
534 pktlen |= (hdr[hdrlen++] = *(*datap)++ << 16 );
535 pktlen |= (hdr[hdrlen++] = *(*datap)++ << 8 );
536 pktlen |= (hdr[hdrlen++] = *(*datap)++ << 0 );
539 pktlen = 0;/* to indicate partial length */
543 pkttype = (ctb >> 2) & 0xf;
544 lenuint8_ts = ((ctb & 3) == 3) ? 0 : (1 << (ctb & 3));
546 pktlen = 0; /* don't know the value */
549 if (*datap + lenuint8_ts > endp) {
550 printk("ksign: length uint8_ts missing\n");
553 for( ; lenuint8_ts; lenuint8_ts-- ) {
555 pktlen |= hdr[hdrlen++] = *(*datap)++;
560 if (*datap + pktlen > endp) {
561 printk("ksign: packet length longer than available data\n");
565 /* deal with the next packet appropriately */
568 rc = ksign_parse_key(*datap, *datap + pktlen, hdr, hdrlen, pkfnx, data);
571 rc = ksign_parse_signature(*datap, *datap + pktlen, sigfnx, data);
574 rc = ksign_parse_user_id(*datap, *datap + pktlen, uidfnx, data);
577 rc = 0; /* unknown packet */
584 } /* end ksign_parse_one_packet() */
586 /*****************************************************************************/
588 * parse the contents of a packet buffer, passing the signature, public key and
589 * user ID to the caller's callback functions
591 int ksign_parse_packets(const uint8_t *buf,
593 ksign_signature_actor_t sigfnx,
594 ksign_public_key_actor_t pkfnx,
595 ksign_user_id_actor_t uidfnx,
598 const uint8_t *datap, *endp;
604 rc = ksign_parse_one_packet(&datap, endp,
605 sigfnx, pkfnx, uidfnx, data);
606 } while (rc == 0 && datap < endp);
609 } /* end ksign_parse_packets() */