static bool data_eq(const data_t *d1, const data_t *d2) { if (d1 == d2) return true; if ((d1 == NULL) || (d2 == NULL)) return false; return (d1->int1 == d2->int1) && (d1->int2 == d2->int2) && (d1->int3 == d2->int3) && (d1->int4 == d2->int4) && (d1->int5 == d2->int5) && (d1->int6 == d2->int6) && buf_eq(&d1->buf, &d2->buf); }
int mix_dearmor(BUFFER *in, BUFFER *out) { BUFFER *line, *md; int tempbuf = 0; int err = 0; line = buf_new(); md = buf_new(); if (in == out) { tempbuf = 1; out = buf_new(); } do { err = buf_getline(in, line); if (err == -1) goto end; } while (!bufeq(line, begin_remailer)); do { /* skip lines before message digest */ if (buf_getline(in, md) == -1) break; } while (strlen(md->data) != 24); decode(in, out); err = buf_getline(in, line); if (err != 0 || !bufeq(line, end_remailer)) err = -1; else { digest_md5(out, line); encode(line, 0); if (!buf_eq(md, line)) err = -1; if (out->length != 20480) err = -1; } end: if (err == -1) errlog(NOTICE, "Malformatted message.\n"); if (tempbuf) { buf_move(in, out); buf_free(out); } buf_free(line); buf_free(md); return (err); }
int mix2_decrypt(BUFFER *m) /* 0: ok * -1: error * -2: old message */ { int err = 0; int i,rsalen,rsalen_as_byte; BUFFER *privkey; BUFFER *keyid; BUFFER *dec, *deskey; BUFFER *packetid, *mid, *digest, *addr, *temp, *iv, *ivvec; int type, packet = 0, numpackets = 0, timestamp = 0; BUFFER *body; BUFFER *header, *out; BUFFER *otherdigest, *bodydigest, *antitag, *extract; BUFFER *ttedigest, *hkey, *aes_pre_key, *aes_header_key, *aes_body_key, *aes_tte_key, *aes_iv; BUFFER *trail; privkey = buf_new(); keyid = buf_new(); dec = buf_new(); deskey = buf_new(); packetid = buf_new(); mid = buf_new(); digest = buf_new(); addr = buf_new(); temp = buf_new(); iv = buf_new(); ivvec = buf_new(); body = buf_new(); header = buf_new(); out = buf_new(); otherdigest = buf_new(); bodydigest = buf_new(); antitag = buf_new(); extract = buf_new(); ttedigest = buf_new(); hkey = buf_new(); aes_pre_key = buf_new(); aes_header_key = buf_new(); aes_body_key = buf_new(); aes_tte_key = buf_new(); aes_iv = buf_new(); trail=buf_new(); aes_pre_key->sensitive=1; aes_body_key->sensitive=1; aes_tte_key->sensitive=1; dec->sensitive=1; deskey->sensitive=1; extract->sensitive=1; hkey->sensitive=1; privkey->sensitive=1; buf_get(m, keyid, 16); err = db_getseckey(keyid->data, privkey); if (err == -1) { errlog(WARNING, "rem2.c mix2_decrypt not found keyid %s\n", showdata(keyid,0)); goto end; } rsalen_as_byte=buf_getc(m); switch(rsalen_as_byte) { case 128: /* legacy 1024-bit */ rsalen_as_byte=1; rsalen=128; break; case 2: rsalen_as_byte=2; rsalen=256; break; case 3: rsalen_as_byte=3; rsalen=384; break; case 4: rsalen_as_byte=4; rsalen=512; break; default: err = -1; errlog(NOTICE, "problem with RSA key size encoded as %d\n", rsalen_as_byte); goto end; break; } assert(128==rsalen || 256==rsalen || 384==rsalen || 512==rsalen); buf_get(m, extract, rsalen); /* 3DES key and maybe more */ err = pk_decrypt(extract, privkey); if (err == -1) { err = -1; errlog(NOTICE, "Cannot decrypt message.\n"); goto end; } buf_append(body, m->data + 20 * 512, 10240); buf_get(m, iv, 8); buf_get(m, dec, 328); if (128==rsalen) { if (extract->length != 24) { err = -1; errlog(NOTICE, "Cannot decrypt message - RSA 1024 data has wrong length %d not 24.\n", extract->length); /* If this length is greater someone may have wrongly sent digests under 1k RSA. */ goto end; } buf_cat(deskey, extract); } else { if (extract->length != 216) { err = -1; errlog(NOTICE, "Cannot decrypt message - RSA (large key) data has wrong length %d.\n", extract->length); /* supposed to be: * 3DES * hmac key * hmac-sha256(18*512 headers) * hmac-sha256(body) * hmac-sha256(328-block) * aes_pre_key */ goto end; } /* antitagging measure */ buf_get(extract, deskey, 24); buf_get(extract, hkey, 64); buf_get(extract, otherdigest, 32); buf_get(extract, bodydigest, 32); buf_get(extract, ttedigest, 32); buf_get(extract, aes_pre_key, 32); buf_reset(temp); hmac_sha256(body, hkey, temp); if (!buf_eq(bodydigest, temp)) { errlog(NOTICE, "Antitagging test - wrong digest on body.\n"); err = -1; goto end; } buf_reset(temp); hmac_sha256(dec, hkey, temp); if (!buf_eq(ttedigest, temp)) { errlog(NOTICE, "Antitagging test - wrong digest on 328-block.\n"); err = -1; goto end; } /* There is one more test applicable if packet type is 0. */ derive_aes_keys(aes_pre_key, hkey, aes_header_key, aes_body_key, aes_tte_key, aes_iv); buf_aescrypt(dec, aes_tte_key, aes_iv, DECRYPT); } buf_crypt(dec, deskey, iv, DECRYPT); buf_get(dec, packetid, 16); buf_get(dec, deskey, 24); type = buf_getc(dec); switch (type) { case 0: if (rsalen>=256) { buf_append(antitag, m->data + 2*512, 2*512); buf_reset(temp); hmac_sha256(antitag, hkey, temp); if (!buf_eq(otherdigest, temp)) { errlog(NOTICE, "Antitagging test - wrong digest on later header\n"); err = -1; goto end; } } buf_get(dec, ivvec, 152); buf_get(dec, addr, 80); break; case 1: buf_get(dec, mid, 16); buf_get(dec, iv, 8); break; case 2: packet = buf_getc(dec); numpackets = buf_getc(dec); buf_get(dec, mid, 16); buf_get(dec, iv, 8); break; default: errlog(WARNING, "Unknown message type.\n"); err = -1; goto end; } if (dec->data[dec->ptr] == '0' && dec->data[dec->ptr + 1] == '0' && dec->data[dec->ptr + 2] == '0' && dec->data[dec->ptr + 3] == '0' && dec->data[dec->ptr + 4] == '\0') { dec->ptr += 5; timestamp = buf_geti_lo(dec); } else { errlog(LOG, "Ignoring message without timestamp.\n"); err = -1; goto end; } buf_get(dec, digest, 16); /* digest of this block, but not so far as to include the digest */ dec->length = dec->ptr - 16; /* ignore digest */ dec->ptr = dec->length; /* If using 1024-bit RSA this is the only integrity protection. (It is still present but less important with larger key sizes.) if (!isdigest_md5(dec, digest)) { errlog(NOTICE, "Message digest does not match.\n"); err = -1; goto end; } /* Statistics are gathered in the isnewid() function. */ switch (isnewid(packetid, rsalen_as_byte, timestamp * SECONDSPERDAY)) { case 0: err = -2; /* redundant message */ goto end; case -1: err = -1; /* future timestamp */ goto end; } if (rsalen == 128) { /* skip either 1 or 2 blocks of 512 bytes */ buf_append(trail, m->data + 512, 19*512); } else { /* and AES */ buf_aescrypt(body, aes_body_key, aes_iv, DECRYPT); buf_append(trail, m->data + 2*512, 19*512); buf_aescrypt(trail, aes_header_key, aes_iv, DECRYPT); } switch (type) { case 0: buf_chop(addr); buf_cat(out, addr); buf_nl(out); for (i = 0; i < 19; i++) { buf_reset(header); buf_append(header, trail->data + i * 512, 512); buf_reset(iv); buf_append(iv, ivvec->data + i * 8, 8); buf_crypt(header, deskey, iv, DECRYPT); buf_cat(out, header); } buf_reset(header); buf_pad(header, 512); /* one block of 512 random data regardless of RSA key size */ buf_cat(out, header); buf_reset(iv); buf_append(iv, ivvec->data + 144, 8); buf_crypt(body, deskey, iv, DECRYPT); buf_cat(out, body); mix_pool(out, INTERMEDIATE, -1); break; case 1: buf_crypt(body, deskey, iv, DECRYPT); err = v2body_setlen(body); if (err == -1) goto end; assert(body->ptr == 4); v2body(body); break; case 2: buf_crypt(body, deskey, iv, DECRYPT); v2partial(body, mid, packet, numpackets); break; } end: buf_free(addr); buf_free(aes_body_key); buf_free(aes_header_key); buf_free(aes_iv); buf_free(aes_pre_key); buf_free(aes_tte_key); buf_free(antitag); buf_free(body); buf_free(bodydigest); buf_free(dec); buf_free(deskey); buf_free(digest); buf_free(extract); buf_free(header); buf_free(hkey); buf_free(iv); buf_free(ivvec); buf_free(keyid); buf_free(mid); buf_free(otherdigest); buf_free(out); buf_free(packetid); buf_free(privkey); buf_free(temp); buf_free(trail); buf_free(ttedigest); return (err); }
int pgpdb_getnext(KEYRING *keydb, BUFFER *key, BUFFER *keyid, BUFFER *userid) /* store next key from keydb with specified keyid/userid in key. */ { int found = 0; int type; long ptr; int tempbuf = 0; BUFFER *p, *i, *thisid; p = buf_new(); i = buf_new(); thisid = buf_new(); if (key == NULL) { tempbuf = 1; key = buf_new(); } assert(key != keyid); while (!found) { buf_clear(key); type = pgp_getpacket(keydb->db, key); if (type == -1) break; if (type != PGP_PUBKEY && type != PGP_SECKEY) continue; if ((keyid == NULL || keyid->length == 0) && (userid == NULL || userid->length == 0)) found = 1; if (keyid && keyid->length > 0) { pgp_keyid(key, thisid); if (buf_eq(keyid, thisid)) found = 1; } pgp_packet(key, type); while ((ptr = keydb->db->ptr, type = pgp_getpacket(keydb->db, p)) > 0) { switch (type) { case PGP_SECKEY: case PGP_PUBKEY: keydb->db->ptr = ptr; goto nextkey; case PGP_PUBSUBKEY: case PGP_SECSUBKEY: if (keyid && keyid->length > 0) { pgp_keyid(p, thisid); if (buf_eq(keyid, thisid)) found = 1; } break; case PGP_USERID: #ifdef DEBUG printf("%s\n", p->data); #endif /* DEBUG */ if (userid && userid->length > 0 && bufifind(p, userid->data)) found = 1; break; } pgp_packet(p, type); buf_cat(key, p); } nextkey: ; } if (tempbuf) buf_free(key); buf_free(p); buf_free(i); buf_free(thisid); return (found ? 0 : -1); }