]> the.earth.li Git - onak.git/commitdiff
Add a hash helper
authorJonathan McDowell <noodles@earth.li>
Tue, 12 Sep 2023 09:13:39 +0000 (14:43 +0530)
committerJonathan McDowell <noodles@earth.li>
Thu, 14 Sep 2023 04:55:00 +0000 (10:25 +0530)
Rather than ifdef'ing hash contexts everywhere we want to use them, wrap
them up in a helper.

CMakeLists.txt
hash-helper.c [new file with mode: 0644]
hash-helper.h [new file with mode: 0644]
sigcheck.c

index c3c0894a4f007f99b4c8b5b7dddf0797521ca54e..581e84911c335781917440d4a8c603a6f4db2384 100644 (file)
@@ -36,9 +36,9 @@ endif()
 
 # Core objects
 add_library(libonak STATIC armor.c charfuncs.c cleankey.c cleanup.c decodekey.c
-       getcgi.c hash.c keyarray.c keyid.c keyindex.c ll.c log.c marshal.c
-       mem.c merge.c onak-conf.c parsekey.c photoid.c rsa.c sigcheck.c sendsync.c
-       sha1x.c wordlist.c)
+       getcgi.c hash.c hash-helper.c keyarray.c keyid.c keyindex.c ll.c log.c
+       marshal.c mem.c merge.c onak-conf.c parsekey.c photoid.c rsa.c
+       sigcheck.c sendsync.c sha1x.c wordlist.c)
 set(LIBONAK_LIBRARIES "")
 
 # Ideally use Nettle, fall back to our own md5/sha1 routines otherwise
diff --git a/hash-helper.c b/hash-helper.c
new file mode 100644 (file)
index 0000000..02b62d9
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * hash-helper.c - Helper functions for calculating hashes
+ *
+ * Copyright Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "build-config.h"
+#include "hash-helper.h"
+#include "onak.h"
+#include "openpgp.h"
+
+onak_status_t onak_hash(struct onak_hash_data *data, uint8_t *hash)
+{
+       struct onak_hash_ctx hash_ctx;
+       int i;
+
+       if (data == NULL) {
+               return ONAK_E_INVALID_PARAM;
+       }
+
+       if (data->chunks > MAX_HASH_CHUNKS) {
+               return ONAK_E_INVALID_PARAM;
+       }
+
+       switch (data->hashtype) {
+       case OPENPGP_HASH_MD5:
+               md5_init(&hash_ctx.md5);
+               for (i = 0; i < data->chunks; i++) {
+                       md5_update(&hash_ctx.md5, data->len[i], data->data[i]);
+               }
+               md5_digest(&hash_ctx.md5, MD5_DIGEST_SIZE, hash);
+               break;
+       case OPENPGP_HASH_SHA1:
+               sha1_init(&hash_ctx.sha1);
+               for (i = 0; i < data->chunks; i++) {
+                       sha1_update(&hash_ctx.sha1, data->len[i], data->data[i]);
+               }
+               sha1_digest(&hash_ctx.sha1, SHA1_DIGEST_SIZE, hash);
+               break;
+       case OPENPGP_HASH_SHA1X:
+               sha1x_init(&hash_ctx.sha1x);
+               for (i = 0; i < data->chunks; i++) {
+                       sha1x_update(&hash_ctx.sha1x, data->len[i], data->data[i]);
+               }
+               sha1x_digest(&hash_ctx.sha1x, SHA1X_DIGEST_SIZE, hash);
+               break;
+#ifdef HAVE_NETTLE
+       case OPENPGP_HASH_RIPEMD160:
+               ripemd160_init(&hash_ctx.ripemd160);
+               for (i = 0; i < data->chunks; i++) {
+                       ripemd160_update(&hash_ctx.ripemd160, data->len[i],
+                               data->data[i]);
+               }
+               ripemd160_digest(&hash_ctx.ripemd160, RIPEMD160_DIGEST_SIZE,
+                       hash);
+               break;
+       case OPENPGP_HASH_SHA224:
+               sha224_init(&hash_ctx.sha224);
+               for (i = 0; i < data->chunks; i++) {
+                       sha224_update(&hash_ctx.sha224, data->len[i],
+                               data->data[i]);
+               }
+               sha224_digest(&hash_ctx.sha224, SHA224_DIGEST_SIZE, hash);
+               break;
+       case OPENPGP_HASH_SHA256:
+               sha256_init(&hash_ctx.sha256);
+               for (i = 0; i < data->chunks; i++) {
+                       sha256_update(&hash_ctx.sha256, data->len[i],
+                               data->data[i]);
+               }
+               sha256_digest(&hash_ctx.sha256, SHA256_DIGEST_SIZE, hash);
+               break;
+       case OPENPGP_HASH_SHA384:
+               sha384_init(&hash_ctx.sha384);
+               for (i = 0; i < data->chunks; i++) {
+                       sha384_update(&hash_ctx.sha384, data->len[i],
+                               data->data[i]);
+               }
+               sha384_digest(&hash_ctx.sha384, SHA384_DIGEST_SIZE, hash);
+               break;
+       case OPENPGP_HASH_SHA512:
+               sha512_init(&hash_ctx.sha512);
+               for (i = 0; i < data->chunks; i++) {
+                       sha512_update(&hash_ctx.sha512, data->len[i],
+                               data->data[i]);
+               }
+               sha512_digest(&hash_ctx.sha512, SHA512_DIGEST_SIZE, hash);
+               break;
+#endif
+       default:
+               return ONAK_E_UNSUPPORTED_FEATURE;
+       }
+
+       return ONAK_E_OK;
+}
diff --git a/hash-helper.h b/hash-helper.h
new file mode 100644 (file)
index 0000000..adb217c
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * hash-helper.h - Helper functions for calculating hashes
+ *
+ * Copyright Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HASH_HELPER_H__
+#define __HASH_HELPER_H__
+
+#include <stdint.h>
+
+#include "build-config.h"
+
+#ifdef HAVE_NETTLE
+#include <nettle/md5.h>
+#include <nettle/ripemd160.h>
+#include <nettle/sha.h>
+#else
+#include "md5.h"
+#include "sha1.h"
+#endif
+
+#include "onak.h"
+#include "sha1x.h"
+
+#define MAX_HASH_CHUNKS                8
+
+struct onak_hash_ctx {
+       uint8_t type;
+       union {
+               struct sha1_ctx sha1;
+               struct sha1x_ctx sha1x;
+               struct md5_ctx md5;
+#ifdef HAVE_NETTLE
+               struct ripemd160_ctx ripemd160;
+               struct sha224_ctx sha224;
+               struct sha256_ctx sha256;
+               struct sha384_ctx sha384;
+               struct sha512_ctx sha512;
+#endif
+       };
+};
+
+struct onak_hash_data {
+       uint8_t hashtype;
+       uint8_t chunks;
+       size_t len[MAX_HASH_CHUNKS];
+       uint8_t *data[MAX_HASH_CHUNKS];
+};
+
+onak_status_t onak_hash(struct onak_hash_data *data, uint8_t *hash);
+
+#endif /* __HASH_HELPER_H__ */
index b59798b3de3043574232607b120cce9cb8a57821..29ab652e71dda830273b4f45c1bd994094ece9e0 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "build-config.h"
 #include "decodekey.h"
+#include "hash-helper.h"
 #include "keyid.h"
 #include "keystructs.h"
 #include "log.h"
 #include "openpgp.h"
 #include "sigcheck.h"
 
-#ifdef HAVE_NETTLE
-#include <nettle/md5.h>
-#include <nettle/ripemd160.h>
-#include <nettle/sha.h>
-#else
-#include "md5.h"
-#include "sha1.h"
-#endif
-
-#include "sha1x.h"
-
 #ifdef HAVE_CRYPTO
 #include <gmp.h>
 #include <nettle/dsa.h>
@@ -530,27 +520,17 @@ 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;
+       int i;
        uint64_t keyid;
        onak_status_t res;
 
        *hashtype = 0;
        *sighash = NULL;
+       memset(&hashdata, 0, sizeof(hashdata));
 
        switch (sig->data[0]) {
        case 2:
@@ -558,11 +538,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];
 
@@ -571,31 +551,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) {
@@ -630,9 +610,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 ==
@@ -641,23 +621,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;
@@ -665,9 +645,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];
@@ -679,11 +659,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];
 
@@ -694,9 +674,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 ==
@@ -705,23 +685,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;
@@ -733,9 +713,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];
@@ -745,74 +725,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;
 }