Browse Source

add support for DH keys

Signed-off-by: Steffen Jaeckel <[email protected]>

# Conflicts:
#	src/pk/dh/dh_import.c
#	src/pk/dh/dh_set.c
#	src/pk/dh/dh_set_pg_dhparam.c
Steffen Jaeckel 3 years ago
parent
commit
26fbebb9d0

+ 2 - 0
src/headers/tomcrypt_pk.h

@@ -143,6 +143,8 @@ int dh_get_groupsize(const dh_key *key);
 
 int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key);
 int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key);
+int dh_import_pkcs8(const unsigned char *in, unsigned long inlen,
+                    const password_ctx  *pw_ctx, dh_key *key);
 
 int dh_set_pg(const unsigned char *p, unsigned long plen,
               const unsigned char *g, unsigned long glen,

+ 3 - 0
src/headers/tomcrypt_private.h

@@ -52,6 +52,7 @@ enum ltc_oid_id {
    LTC_OID_EC_PRIMEF,
    LTC_OID_X25519,
    LTC_OID_ED25519,
+   LTC_OID_DH,
 };
 
 /*
@@ -369,7 +370,9 @@ int rsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, rsa_ke
 #ifdef LTC_MDH
 extern const ltc_dh_set_type ltc_dh_sets[];
 
+int dh_init(dh_key *key);
 int dh_check_pubkey(const dh_key *key);
+int dh_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dh_key *key);
 #endif /* LTC_MDH */
 
 /* ---- ECC Routines ---- */

+ 6 - 0
src/misc/pem/pem_pkcs.c

@@ -93,6 +93,12 @@ retry:
          goto cleanup;
       }
       switch (pka) {
+#ifdef LTC_MDH
+         case LTC_OID_DH:
+            err = dh_import_pkcs8_asn1(alg_id, priv_key, &k->u.dh);
+            k->id = LTC_PKA_DH;
+            break;
+#endif
 #ifdef LTC_MDSA
          case LTC_OID_DSA:
             err = dsa_import_pkcs8_asn1(alg_id, priv_key, &k->u.dsa);

+ 1 - 0
src/pk/asn1/oid/pk_get.c

@@ -17,6 +17,7 @@ static const oid_table_entry pka_oids[] = {
                                               { LTC_OID_EC_PRIMEF, LTC_PKA_EC,         "1.2.840.10045.1.1" },
                                               { LTC_OID_X25519,    LTC_PKA_CURVE25519, "1.3.101.110" },
                                               { LTC_OID_ED25519,   LTC_PKA_CURVE25519, "1.3.101.112" },
+                                              { LTC_OID_DH,        LTC_PKA_DH,         "1.2.840.113549.1.3.1" },
 };
 
 /*

+ 15 - 0
src/pk/dh/dh.c

@@ -224,4 +224,19 @@ int dh_get_groupsize(const dh_key *key)
    return mp_unsigned_bin_size(key->prime);
 }
 
+/**
+  Init a DH key
+  @param key   The DH key to initialize
+  @return CRYPT_OK if successful
+*/
+int dh_init(dh_key *key)
+{
+   int err;
+   LTC_ARGCHK(key != NULL);
+   if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) {
+      return err;
+   }
+   return CRYPT_OK;
+}
+
 #endif /* LTC_MDH */

+ 1 - 1
src/pk/dh/dh_import.c

@@ -22,7 +22,7 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
    LTC_ARGCHK(key != NULL);
 
    /* init */
-   if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) {
+   if ((err = dh_init(key)) != CRYPT_OK) {
       return err;
    }
 

+ 87 - 0
src/pk/dh/dh_import_pkcs8.c

@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+#include "tomcrypt_private.h"
+
+#ifdef LTC_MDH
+
+int dh_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dh_key *key)
+{
+   int           err;
+
+   LTC_ARGCHK(key != NULL);
+
+   if (!alg_id->child ||
+         !LTC_ASN1_IS_TYPE(alg_id->child->next, LTC_ASN1_SEQUENCE) ||
+         !LTC_ASN1_IS_TYPE(alg_id->child->next->child, LTC_ASN1_INTEGER) ||
+         !LTC_ASN1_IS_TYPE(alg_id->child->next->child->next, LTC_ASN1_INTEGER)) {
+      return CRYPT_PK_INVALID_TYPE;
+   }
+
+   if ((err = dh_init(key)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((err = mp_copy(alg_id->child->next->child->data, key->prime)) != CRYPT_OK) {
+      goto error;
+   }
+   if ((err = mp_copy(alg_id->child->next->child->next->data, key->base)) != CRYPT_OK) {
+      goto error;
+   }
+
+   if ((err = der_decode_integer(priv_key->data, priv_key->size, key->x)) != CRYPT_OK) {
+      goto error;
+   }
+   /* compute public key: y = (base ^ x) mod prime */
+   if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) {
+      goto error;
+   }
+   /* check public key */
+   if ((err = dh_check_pubkey(key)) != CRYPT_OK) {
+      goto error;
+   }
+   key->type = PK_PRIVATE;
+
+   return CRYPT_OK;
+error:
+   dh_free(key);
+   return err;
+}
+
+/**
+  Import a DH key in PKCS#8 format
+  @param in        The packet to import from
+  @param inlen     It's length (octets)
+  @param pw_ctx    The password context when decrypting the private key
+  @param key       [out] Destination for newly imported key
+  @return CRYPT_OK if successful, on error all allocated memory is freed automatically
+*/
+int dh_import_pkcs8(const unsigned char *in, unsigned long inlen,
+                    const password_ctx  *pw_ctx, dh_key *key)
+{
+   int           err;
+   ltc_asn1_list *l = NULL;
+   ltc_asn1_list *alg_id, *priv_key;
+   enum ltc_oid_id pka;
+
+   LTC_ARGCHK(in != NULL);
+
+   if ((err = pkcs8_decode_flexi(in, inlen, pw_ctx, &l)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = pkcs8_get_children(l, &pka, &alg_id, &priv_key)) != CRYPT_OK) {
+      goto LBL_DER_FREE;
+   }
+   if (pka != LTC_OID_DH) {
+      err = CRYPT_INVALID_PACKET;
+      goto LBL_DER_FREE;
+   }
+
+   err = dh_import_pkcs8_asn1(alg_id, priv_key, key);
+
+LBL_DER_FREE:
+   der_free_sequence_flexi(l);
+   return err;
+}
+
+#endif /* LTC_MDH */

+ 3 - 2
src/pk/dh/dh_set.c

@@ -26,7 +26,7 @@ int dh_set_pg(const unsigned char *p, unsigned long plen,
    LTC_ARGCHK(g           != NULL);
    LTC_ARGCHK(ltc_mp.name != NULL);
 
-   if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) {
+   if ((err = dh_init(key)) != CRYPT_OK) {
       return err;
    }
 
@@ -58,9 +58,10 @@ int dh_set_pg_groupsize(int groupsize, dh_key *key)
    for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++);
    if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE;
 
-   if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) {
+   if ((err = dh_init(key)) != CRYPT_OK) {
       return err;
    }
+
    if ((err = mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK)  { goto LBL_ERR; }
    if ((err = mp_read_radix(key->prime, ltc_dh_sets[i].prime, 16)) != CRYPT_OK) { goto LBL_ERR; }
 

+ 1 - 1
src/pk/dh/dh_set_pg_dhparam.c

@@ -24,7 +24,7 @@ int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh
    LTC_ARGCHK(dhparam     != NULL);
    LTC_ARGCHK(dhparamlen  > 0);
 
-   if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) {
+   if ((err = dh_init(key)) != CRYPT_OK) {
       return err;
    }
    if ((err = der_decode_sequence_multi(dhparam, dhparamlen,

+ 11 - 0
tests/pem/dh-encrypted.pk8

@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBjTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI+JYkd4NoIU4CAggA
+MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCNnY9OuYIvCurJu9sEYkz6BIIB
+MGzX4GwCvBQV/dOiy0PvbY443xkKZHPTtNbirE+9NLVVrTI7EUQv5UO5Xl0wVHje
+R4hADBzpIKAd0zjsGYfMQ6rEabIdO4R+UBKoibTgyOzt7Y5Ge/4+pYy14bMFeZ44
+6OaP6jXRsn1/DIi0mxcBo9eDfZX3FzgANWiDvFA2VWC+qEbsm4JBB8uDJ+aWtjyR
+mct/FXzGHwi+IGuPBzo9dIywisW4whmBwh1XpFBMxjmMLqWInuUailAkIARJ0w04
+GdGZ6HYlKmsTvAKv4WRK+EnwZ8JmBiVl6ulcX8k1zbrT2ElyBUCFneMktFKULE1l
+myVMuAQCuuGfWdquegqLOyvgK6S9p3wfVyzkney8qBN07WZHE+UUW8AQrZS6J5nS
+wSAjBu3wmDmDo7AWEQZFMK4=
+-----END ENCRYPTED PRIVATE KEY-----

+ 9 - 0
tests/pem/dh.pk8

@@ -0,0 +1,9 @@
+-----BEGIN PRIVATE KEY-----
+MIIBIQIBADCBlQYJKoZIhvcNAQMBMIGHAoGBANL7HwrNQcDtDCkqzYxzMCFLFCdJ
+qkp7v5RtqHzNM+5VQZp/xo2BzWF5PLJQ9ssE5QYtl7zQGM8eK1Z4/ACKwm2GJR4d
+5kkr3SCbK2zoedDj/LJy1xBWjtRa81W6LtBAnEH7w5hgwJiPPFbc5X2i2uv6bcRk
+wk7SBstON/Nn+7KLAgECBIGDAoGAceccNmflU1P1oAb6pyQoWKokZXdkwSepQo65
+Fub3B2YW9/qI7DHiSskfQptl4ifeQRFGwq11kqsNUI+mcdGODs1r5MUZ99g1Bh3u
+X3XOfTgZoyDY5uHwBLl6HndN/QcJ+nq9y3URt4ltklQQ3WFPzHTdJNg9qBeLqNVe
+GaFVEJo=
+-----END PRIVATE KEY-----

+ 6 - 0
tests/pem_test.c

@@ -65,6 +65,7 @@ static int s_key_cmp(ltc_pka_key *key)
 #endif
          break;
       case LTC_PKA_CURVE25519:
+      case LTC_PKA_DH:
          return CRYPT_OK;
       default:
          return CRYPT_INVALID_ARG;
@@ -97,6 +98,11 @@ static int s_pem_decode_f(FILE *f, void *key)
 static void s_pem_free_key(ltc_pka_key *key)
 {
    switch (key->id) {
+      case LTC_PKA_DH:
+#if defined(LTC_MDH)
+         dh_free(&key->u.dh);
+#endif
+         break;
       case LTC_PKA_DSA:
 #if defined(LTC_MDSA)
          dsa_free(&key->u.dsa);