X-Git-Url: http://the.earth.li/gitweb/?a=blobdiff_plain;f=sigcheck.c;h=c1a7ce541f3931aaa40640919dec99b810b8f794;hb=HEAD;hp=2f72a492af2599859efc1ae8079c3eae0a4d2a4d;hpb=c981a80699901eb3d513a4cc9355574a69016037;p=onak.git diff --git a/sigcheck.c b/sigcheck.c index 2f72a49..c1a7ce5 100644 --- a/sigcheck.c +++ b/sigcheck.c @@ -21,6 +21,7 @@ #include "build-config.h" #include "decodekey.h" +#include "hash-helper.h" #include "keyid.h" #include "keystructs.h" #include "log.h" @@ -28,17 +29,6 @@ #include "openpgp.h" #include "sigcheck.h" -#ifdef HAVE_NETTLE -#include -#include -#include -#else -#include "md5.h" -#include "sha1.h" -#endif - -#include "sha1x.h" - #ifdef HAVE_CRYPTO #include #include @@ -48,6 +38,17 @@ #include #include #include "rsa.h" + +#ifndef HAVE_NETTLE_GET_SECP_256R1 +#define nettle_get_secp_256r1() &nettle_secp_256r1 +#endif +#ifndef HAVE_NETTLE_GET_SECP_384R1 +#define nettle_get_secp_384r1() &nettle_secp_384r1 +#endif +#ifndef HAVE_NETTLE_GET_SECP_521R1 +#define nettle_get_secp_521r1() &nettle_secp_521r1 +#endif + #endif /* Take an MPI from a buffer and import it into a GMP mpz_t */ @@ -115,7 +116,7 @@ static void onak_free_key_material(struct onak_key_material *key) static onak_status_t onak_parse_key_material(struct openpgp_packet *pk, struct onak_key_material *key) { - int i, len, ofs; + int len, ofs; enum onak_oid oid; mpz_t x, y; onak_status_t ret = ONAK_E_OK; @@ -262,6 +263,12 @@ static onak_status_t onak_parse_key_material(struct openpgp_packet *pk, return ONAK_E_UNSUPPORTED_FEATURE; } + /* + * Keep scan-build happy; we bump this in MPI_TO_MPZ and then don't use + * it again the last time we do so. + */ + (void)ofs; + key->type = pk->data[5]; if (ret != ONAK_E_OK) { @@ -271,7 +278,7 @@ static onak_status_t onak_parse_key_material(struct openpgp_packet *pk, return ret; } -onak_status_t onak_check_hash_sig(struct openpgp_publickey *sigkey, +onak_status_t onak_check_hash_sig(struct openpgp_packet *sigkey, struct openpgp_packet *sig, uint8_t *hash, uint8_t hashtype) @@ -279,12 +286,13 @@ onak_status_t onak_check_hash_sig(struct openpgp_publickey *sigkey, onak_status_t ret; struct onak_key_material pubkey; struct dsa_signature dsasig; + uint8_t sigkeytype; uint8_t edsig[64]; - uint64_t keyid; int len, ofs; + size_t count; mpz_t s; - ret = onak_parse_key_material(sigkey->publickey, &pubkey); + ret = onak_parse_key_material(sigkey, &pubkey); if (ret != ONAK_E_OK) { return ret; } @@ -295,29 +303,51 @@ onak_status_t onak_check_hash_sig(struct openpgp_publickey *sigkey, goto out; } - /* Is the key the same type as the signature we're checking? */ - if (pubkey.type != sig->data[2]) { - ret = ONAK_E_INVALID_PARAM; - goto out; - } + if (sig->data[0] == 3) { + /* Must be 5 bytes hashed */ + if (sig->data[1] != 5) { + ret = ONAK_E_INVALID_PARAM; + goto out; + } - /* Skip the hashed data */ - ofs = (sig->data[4] << 8) + sig->data[5] + 6; - if (sig->length < ofs + 2) { - ret = ONAK_E_INVALID_PKT; + /* Need at least 19 bytes for the sig header */ + if (sig->length < 19) { + ret = ONAK_E_INVALID_PKT; + goto out; + } + + /* Skip to the signature material */ + ofs = 19; + sigkeytype = sig->data[15]; + } else if (sig->data[0] >= 4) { + /* Skip the hashed data */ + ofs = (sig->data[4] << 8) + sig->data[5] + 6; + if (sig->length < ofs + 2) { + ret = ONAK_E_INVALID_PKT; + goto out; + } + /* Skip the unhashed data */ + ofs += (sig->data[ofs] << 8) + sig->data[ofs + 1] + 2; + if (sig->length < ofs + 2) { + ret = ONAK_E_INVALID_PKT; + goto out; + } + /* Skip the sig hash bytes */ + ofs += 2; + sigkeytype = sig->data[2]; + } else { + ret = ONAK_E_UNSUPPORTED_FEATURE; goto out; } - /* Skip the unhashed data */ - ofs += (sig->data[ofs] << 8) + sig->data[ofs + 1] + 2; - if (sig->length < ofs + 2) { - ret = ONAK_E_INVALID_PKT; + + /* Is the key the same type as the signature we're checking? */ + if (pubkey.type != sigkeytype) { + ret = ONAK_E_INVALID_PARAM; goto out; } - /* Skip the sig hash bytes */ - ofs += 2; /* Parse the actual signature values */ - switch (sig->data[2]) { + switch (sigkeytype) { case OPENPGP_PKALGO_ECDSA: case OPENPGP_PKALGO_DSA: mpz_init(dsasig.r); @@ -332,8 +362,22 @@ onak_status_t onak_check_hash_sig(struct openpgp_publickey *sigkey, MPI_TO_MPZ(sig, dsasig.r); if (ret == ONAK_E_OK) MPI_TO_MPZ(sig, dsasig.s); - mpz_export(edsig, NULL, 1, 1, 0, 0, dsasig.r); - mpz_export(&edsig[32], NULL, 1, 1, 0, 0, dsasig.s); + mpz_export(edsig, &count, 1, 1, 0, 0, dsasig.r); + if (count < 32) { + memmove(&edsig[32 - count], edsig, count); + while (count < 32) { + count++; + edsig[32 - count] = 0; + } + } + mpz_export(&edsig[32], &count, 1, 1, 0, 0, dsasig.s); + if (count < 32) { + memmove(&edsig[32 - count], edsig, count); + while (count < 32) { + count++; + edsig[32 - count] = 0; + } + } break; case OPENPGP_PKALGO_RSA: case OPENPGP_PKALGO_RSA_SIGN: @@ -398,6 +442,7 @@ onak_status_t onak_check_hash_sig(struct openpgp_publickey *sigkey, ret = ecdsa_verify(&pubkey.ecc, SHA1_DIGEST_SIZE, hash, &dsasig) ? ONAK_E_OK : ONAK_E_BAD_SIGNATURE; + break; case KEYHASH(OPENPGP_PKALGO_ECDSA, OPENPGP_HASH_SHA256): ret = ecdsa_verify(&pubkey.ecc, SHA256_DIGEST_SIZE, hash, &dsasig) ? @@ -466,7 +511,7 @@ onak_status_t onak_check_hash_sig(struct openpgp_publickey *sigkey, } sigerr: - switch (sig->data[2]) { + switch (sigkeytype) { case OPENPGP_PKALGO_ECDSA: case OPENPGP_PKALGO_EDDSA: case OPENPGP_PKALGO_DSA: @@ -495,27 +540,16 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, uint8_t **sighash) { size_t siglen, unhashedlen; - struct sha1_ctx sha1_context; - struct sha1x_ctx sha1x_context; - struct md5_ctx md5_context; -#ifdef HAVE_NETTLE - struct ripemd160_ctx ripemd160_context; - struct sha224_ctx sha224_context; - struct sha256_ctx sha256_context; - struct sha384_ctx sha384_context; - struct sha512_ctx sha512_context; -#endif + struct onak_hash_data hashdata; uint8_t keyheader[5]; uint8_t packetheader[5]; uint8_t trailer[10]; - uint8_t *hashdata[8]; - size_t hashlen[8]; - int chunks, i; uint64_t keyid; onak_status_t res; *hashtype = 0; *sighash = NULL; + memset(&hashdata, 0, sizeof(hashdata)); switch (sig->data[0]) { case 2: @@ -523,11 +557,11 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, keyheader[0] = 0x99; keyheader[1] = key->publickey->length >> 8; keyheader[2] = key->publickey->length & 0xFF; - hashdata[0] = keyheader; - hashlen[0] = 3; - hashdata[1] = key->publickey->data; - hashlen[1] = key->publickey->length; - chunks = 2; + hashdata.data[0] = keyheader; + hashdata.len[0] = 3; + hashdata.data[1] = key->publickey->data; + hashdata.len[1] = key->publickey->length; + hashdata.chunks = 2; *hashtype = sig->data[16]; @@ -536,31 +570,31 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, packetheader[0] = 0x99; packetheader[1] = packet->length >> 8; packetheader[2] = packet->length & 0xFF; - hashdata[chunks] = packetheader; - hashlen[chunks] = 3; - chunks++; + hashdata.data[hashdata.chunks] = packetheader; + hashdata.len[hashdata.chunks] = 3; + hashdata.chunks++; } // TODO: Things other than UIDS/subkeys? - hashdata[chunks] = packet->data; - hashlen[chunks] = packet->length; - chunks++; + hashdata.data[hashdata.chunks] = packet->data; + hashdata.len[hashdata.chunks] = packet->length; + hashdata.chunks++; } - hashdata[chunks] = &sig->data[2]; - hashlen[chunks] = 5; - chunks++; + hashdata.data[hashdata.chunks] = &sig->data[2]; + hashdata.len[hashdata.chunks] = 5; + hashdata.chunks++; *sighash = &sig->data[17]; break; case 4: keyheader[0] = 0x99; keyheader[1] = key->publickey->length >> 8; keyheader[2] = key->publickey->length & 0xFF; - hashdata[0] = keyheader; - hashlen[0] = 3; - hashdata[1] = key->publickey->data; - hashlen[1] = key->publickey->length; - chunks = 2; + hashdata.data[0] = keyheader; + hashdata.len[0] = 3; + hashdata.data[1] = key->publickey->data; + hashdata.len[1] = key->publickey->length; + hashdata.chunks = 2; /* Check to see if this is an X509 based signature */ if (sig->data[2] == 0 || sig->data[2] == 100) { @@ -595,9 +629,9 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, packetheader[0] = 0x99; packetheader[1] = packet->length >> 8; packetheader[2] = packet->length & 0xFF; - hashdata[chunks] = packetheader; - hashlen[chunks] = 3; - chunks++; + hashdata.data[hashdata.chunks] = packetheader; + hashdata.len[hashdata.chunks] = 3; + hashdata.chunks++; } else if (packet->tag == OPENPGP_PACKET_UID || packet->tag == OPENPGP_PACKET_UAT) { packetheader[0] = (packet->tag == @@ -606,23 +640,23 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, packetheader[2] = (packet->length >> 16) & 0xFF; packetheader[3] = (packet->length >> 8) & 0xFF; packetheader[4] = packet->length & 0xFF; - hashdata[chunks] = packetheader; - hashlen[chunks] = 5; - chunks++; + hashdata.data[hashdata.chunks] = packetheader; + hashdata.len[hashdata.chunks] = 5; + hashdata.chunks++; } - hashdata[chunks] = packet->data; - hashlen[chunks] = packet->length; - chunks++; + hashdata.data[hashdata.chunks] = packet->data; + hashdata.len[hashdata.chunks] = packet->length; + hashdata.chunks++; } - hashdata[chunks] = sig->data; - hashlen[chunks] = siglen = (sig->data[4] << 8) + + hashdata.data[hashdata.chunks] = sig->data; + hashdata.len[hashdata.chunks] = siglen = (sig->data[4] << 8) + sig->data[5] + 6;; if (siglen > sig->length) { /* Signature data exceed packet length, bogus */ return ONAK_E_INVALID_PKT; } - chunks++; + hashdata.chunks++; trailer[0] = 4; trailer[1] = 0xFF; @@ -630,9 +664,9 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, trailer[3] = (siglen >> 16) & 0xFF; trailer[4] = (siglen >> 8) & 0xFF; trailer[5] = siglen & 0xFF; - hashdata[chunks] = trailer; - hashlen[chunks] = 6; - chunks++; + hashdata.data[hashdata.chunks] = trailer; + hashdata.len[hashdata.chunks] = 6; + hashdata.chunks++; unhashedlen = (sig->data[siglen] << 8) + sig->data[siglen + 1]; @@ -644,11 +678,11 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, keyheader[2] = 0; keyheader[3] = key->publickey->length >> 8; keyheader[4] = key->publickey->length & 0xFF; - hashdata[0] = keyheader; - hashlen[0] = 5; - hashdata[1] = key->publickey->data; - hashlen[1] = key->publickey->length; - chunks = 2; + hashdata.data[0] = keyheader; + hashdata.len[0] = 5; + hashdata.data[1] = key->publickey->data; + hashdata.len[1] = key->publickey->length; + hashdata.chunks = 2; *hashtype = sig->data[3]; @@ -659,9 +693,9 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, packetheader[2] = 0; packetheader[3] = packet->length >> 8; packetheader[4] = packet->length & 0xFF; - hashdata[chunks] = packetheader; - hashlen[chunks] = 5; - chunks++; + hashdata.data[hashdata.chunks] = packetheader; + hashdata.len[hashdata.chunks] = 5; + hashdata.chunks++; } else if (packet->tag == OPENPGP_PACKET_UID || packet->tag == OPENPGP_PACKET_UAT) { packetheader[0] = (packet->tag == @@ -670,23 +704,23 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, packetheader[2] = (packet->length >> 16) & 0xFF; packetheader[3] = (packet->length >> 8) & 0xFF; packetheader[4] = packet->length & 0xFF; - hashdata[chunks] = packetheader; - hashlen[chunks] = 5; - chunks++; + hashdata.data[hashdata.chunks] = packetheader; + hashdata.len[hashdata.chunks] = 5; + hashdata.chunks++; } - hashdata[chunks] = packet->data; - hashlen[chunks] = packet->length; - chunks++; + hashdata.data[hashdata.chunks] = packet->data; + hashdata.len[hashdata.chunks] = packet->length; + hashdata.chunks++; } - hashdata[chunks] = sig->data; - hashlen[chunks] = siglen = (sig->data[4] << 8) + + hashdata.data[hashdata.chunks] = sig->data; + hashdata.len[hashdata.chunks] = siglen = (sig->data[4] << 8) + sig->data[5] + 6;; if (siglen > sig->length) { /* Signature data exceed packet length, bogus */ return ONAK_E_INVALID_PKT; } - chunks++; + hashdata.chunks++; trailer[0] = 5; trailer[1] = 0xFF; @@ -698,9 +732,9 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, trailer[7] = (siglen >> 16) & 0xFF; trailer[8] = (siglen >> 8) & 0xFF; trailer[9] = siglen & 0xFF; - hashdata[chunks] = trailer; - hashlen[chunks] = 10; - chunks++; + hashdata.data[hashdata.chunks] = trailer; + hashdata.len[hashdata.chunks] = 10; + hashdata.chunks++; unhashedlen = (sig->data[siglen] << 8) + sig->data[siglen + 1]; @@ -710,74 +744,9 @@ onak_status_t calculate_packet_sighash(struct openpgp_publickey *key, return ONAK_E_UNSUPPORTED_FEATURE; } - switch (*hashtype) { - case OPENPGP_HASH_MD5: - md5_init(&md5_context); - for (i = 0; i < chunks; i++) { - md5_update(&md5_context, hashlen[i], hashdata[i]); - } - md5_digest(&md5_context, MD5_DIGEST_SIZE, hash); - break; - case OPENPGP_HASH_SHA1: - sha1_init(&sha1_context); - for (i = 0; i < chunks; i++) { - sha1_update(&sha1_context, hashlen[i], hashdata[i]); - } - sha1_digest(&sha1_context, SHA1_DIGEST_SIZE, hash); - break; - case OPENPGP_HASH_SHA1X: - sha1x_init(&sha1x_context); - for (i = 0; i < chunks; i++) { - sha1x_update(&sha1x_context, hashlen[i], hashdata[i]); - } - sha1x_digest(&sha1x_context, SHA1X_DIGEST_SIZE, hash); - break; -#ifdef HAVE_NETTLE - case OPENPGP_HASH_RIPEMD160: - ripemd160_init(&ripemd160_context); - for (i = 0; i < chunks; i++) { - ripemd160_update(&ripemd160_context, hashlen[i], - hashdata[i]); - } - ripemd160_digest(&ripemd160_context, RIPEMD160_DIGEST_SIZE, - hash); - break; - case OPENPGP_HASH_SHA224: - sha224_init(&sha224_context); - for (i = 0; i < chunks; i++) { - sha224_update(&sha224_context, hashlen[i], - hashdata[i]); - } - sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash); - break; - case OPENPGP_HASH_SHA256: - sha256_init(&sha256_context); - for (i = 0; i < chunks; i++) { - sha256_update(&sha256_context, hashlen[i], - hashdata[i]); - } - sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash); - break; - case OPENPGP_HASH_SHA384: - sha384_init(&sha384_context); - for (i = 0; i < chunks; i++) { - sha384_update(&sha384_context, hashlen[i], - hashdata[i]); - } - sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash); - break; - case OPENPGP_HASH_SHA512: - sha512_init(&sha512_context); - for (i = 0; i < chunks; i++) { - sha512_update(&sha512_context, hashlen[i], - hashdata[i]); - } - sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash); - break; -#endif - default: - return ONAK_E_UNSUPPORTED_FEATURE; - } + hashdata.hashtype = *hashtype; + + res = onak_hash(&hashdata, hash); - return ONAK_E_OK; + return res; }