瀏覽代碼

add ecdsa key support

Signed-off-by: Steffen Jaeckel <[email protected]>
Steffen Jaeckel 6 年之前
父節點
當前提交
2ff20d7966
共有 1 個文件被更改,包括 127 次插入44 次删除
  1. 127 44
      demos/openssh-privkey.c

+ 127 - 44
demos/openssh-privkey.c

@@ -18,7 +18,7 @@
 #include <tomcrypt_private.h>
 #include <stdarg.h>
 
-static int verbose = 1;
+static int verbose = 0;
 
 static void print_hex(const char* what, const void* v, const unsigned long l)
 {
@@ -68,12 +68,13 @@ static void print_err(const char *fmt, ...)
 
 static void die_(int err, int line)
 {
+   verbose = 1;
    print_err("%3d: LTC sez %s\n", line, error_to_string(err));
    exit(EXIT_FAILURE);
 }
 
 #define die(i) do { die_(i, __LINE__); } while(0)
-#define DIE(s, ...) do { print_err("%3d: " s "\n", __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
+#define DIE(s, ...) do { verbose = 1; print_err("%3d: " s "\n", __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
 
 
 static void check_padding(unsigned char *p, unsigned long len)
@@ -91,6 +92,7 @@ typedef struct pka_key_ {
    enum ltc_oid_id id;
    union {
       curve25519_key ed25519;
+      ecc_key ecdsa;
       rsa_key rsa;
    } u;
 } pka_key;
@@ -135,6 +137,115 @@ const struct ssh_kdf ssh_kdfs[] =
    { 0 },
 };
 
+int ssh_find_init_ecc(const char *pka, pka_key *key)
+{
+   int err;
+   const char* prefix = "ecdsa-sha2-";
+   size_t prefixlen = strlen(prefix);
+   const ltc_ecc_curve *cu;
+   if (strstr(pka, prefix) == NULL) return CRYPT_PK_INVALID_TYPE;
+   if ((err = ecc_find_curve(pka + prefixlen, &cu)) != CRYPT_OK) return err;
+   return ecc_set_curve(cu, &key->u.ecdsa);
+}
+
+int ssh_decode_ecdsa(const unsigned char *in, unsigned long *inlen, pka_key *key)
+{
+   int err;
+   unsigned char groupname[64], group[512], privkey[512];
+   ulong32 groupnamelen = sizeof(groupname), grouplen = sizeof(group), privkeylen = sizeof(privkey);
+
+   if ((err = ssh_decode_sequence_multi(in, inlen,
+                                        LTC_SSHDATA_STRING, group, &groupnamelen,
+                                        LTC_SSHDATA_STRING, group, &grouplen,
+                                        LTC_SSHDATA_STRING, privkey, &privkeylen,
+                                        LTC_SSHDATA_EOL)) != CRYPT_OK) {
+      die(err);
+   }
+
+   if ((err = ecc_set_key(privkey, privkeylen, PK_PRIVATE, &key->u.ecdsa)) != CRYPT_OK) {
+      die(err);
+   }
+
+   key->id = PKA_EC;
+
+   zeromem(groupname, sizeof(groupname));
+   zeromem(group, sizeof(group));
+   zeromem(privkey, sizeof(privkey));
+
+   return err;
+}
+
+int ssh_decode_ed25519(const unsigned char *in, unsigned long *inlen, pka_key *key)
+{
+   int err;
+   unsigned char pubkey[2048], privkey[2048];
+   ulong32 pubkeylen = sizeof(pubkey), privkeylen = sizeof(privkey);
+
+   if ((err = ssh_decode_sequence_multi(in, inlen,
+                                        LTC_SSHDATA_STRING, pubkey, &pubkeylen,
+                                        LTC_SSHDATA_STRING, privkey, &privkeylen,
+                                        LTC_SSHDATA_EOL)) != CRYPT_OK) {
+      die(err);
+   }
+
+   if ((err = ed25519_set_key(privkey, 32, &privkey[32], 32, &key->u.ed25519)) != CRYPT_OK) {
+      die(err);
+   }
+
+   key->id = PKA_ED25519;
+
+   zeromem(pubkey, sizeof(pubkey));
+   zeromem(privkey, sizeof(privkey));
+
+   return err;
+}
+
+int ssh_decode_rsa(const unsigned char *in, unsigned long *inlen, pka_key *key)
+{
+   int err;
+   void *tmp1, *tmp2;
+   if ((err = mp_init_multi(&tmp1, &tmp2, NULL)) != CRYPT_OK) {
+      die(err);
+   }
+   if ((err = rsa_init(&key->u.rsa)) != CRYPT_OK) {
+      die(err);
+   }
+
+   if ((err = ssh_decode_sequence_multi(in, inlen,
+                                        LTC_SSHDATA_MPINT, key->u.rsa.N,
+                                        LTC_SSHDATA_MPINT, key->u.rsa.e,
+                                        LTC_SSHDATA_MPINT, key->u.rsa.d,
+                                        LTC_SSHDATA_MPINT, key->u.rsa.qP,
+                                        LTC_SSHDATA_MPINT, key->u.rsa.q,
+                                        LTC_SSHDATA_MPINT, key->u.rsa.p,
+                                        LTC_SSHDATA_EOL)) != CRYPT_OK) {
+      die(err);
+   }
+
+   if ((err = mp_sub_d(key->u.rsa.p, 1,  tmp1)) != CRYPT_OK)                     { die(err); } /* tmp1 = q-1 */
+   if ((err = mp_sub_d(key->u.rsa.q, 1,  tmp2)) != CRYPT_OK)                     { die(err); } /* tmp2 = p-1 */
+   if ((err = mp_mod( key->u.rsa.d,  tmp1,  key->u.rsa.dP)) != CRYPT_OK)         { die(err); } /* dP = d mod p-1 */
+   if ((err = mp_mod( key->u.rsa.d,  tmp2,  key->u.rsa.dQ)) != CRYPT_OK)         { die(err); } /* dQ = d mod q-1 */
+
+   key->id = PKA_RSA;
+
+   mp_clear_multi(tmp2, tmp1, NULL);
+
+   return err;
+}
+
+struct ssh_pka {
+   const char *name;
+   int (*init)(const char*, pka_key*);
+   int (*decode)(const unsigned char*, unsigned long*, pka_key*);
+};
+
+struct ssh_pka ssh_pkas[] = {
+                             { "ssh-ed25519", NULL,              ssh_decode_ed25519 },
+                             { "ssh-rsa",     NULL,              ssh_decode_rsa },
+                             { NULL,          ssh_find_init_ecc, ssh_decode_ecdsa },
+};
+
 int ssh_decode_private_key(const unsigned char *in, unsigned long *inlen, pka_key *key)
 {
    int err;
@@ -143,7 +254,8 @@ int ssh_decode_private_key(const unsigned char *in, unsigned long *inlen, pka_ke
    ulong32 pkalen = sizeof(pka), pubkeylen = sizeof(pubkey);
    ulong32 privkeylen = sizeof(privkey), commentlen = sizeof(comment);
    unsigned long remaining, cur_len;
-   unsigned char *p;
+   const unsigned char *p;
+   size_t n;
 
    LTC_ARGCHK(in    != NULL);
    LTC_ARGCHK(inlen != NULL);
@@ -163,55 +275,26 @@ int ssh_decode_private_key(const unsigned char *in, unsigned long *inlen, pka_ke
 
    p += cur_len;
    remaining = *inlen - cur_len;
+   cur_len = remaining;
 
-   if (XSTRCMP(pka, "ssh-ed25519") == 0) {
-      cur_len = remaining;
-      if ((err = ssh_decode_sequence_multi(p, &cur_len,
-                                           LTC_SSHDATA_STRING, pubkey, &pubkeylen,
-                                           LTC_SSHDATA_STRING, privkey, &privkeylen,
-                                           LTC_SSHDATA_EOL)) != CRYPT_OK) {
-         die(err);
-      }
-
-      if ((err = ed25519_set_key(privkey, 32, &privkey[32], 32, &key->u.ed25519)) != CRYPT_OK) {
-         die(err);
-      }
-
-      key->id = PKA_ED25519;
-   } else if (XSTRCMP(pka, "ssh-rsa") == 0) {
-      void *tmp1, *tmp2;
-      if ((err = mp_init_multi(&tmp1, &tmp2, NULL)) != CRYPT_OK) {
-         die(err);
-      }
-      if ((err = rsa_init(&key->u.rsa)) != CRYPT_OK) {
-         die(err);
+   for (n = 0; n < sizeof(ssh_pkas)/sizeof(ssh_pkas[0]); ++n) {
+      if (ssh_pkas[n].name != NULL) {
+         if (XSTRCMP(pka, ssh_pkas[n].name) != 0) continue;
+      } else {
+         if ((ssh_pkas[n].init == NULL) ||
+               (ssh_pkas[n].init((char*)pka, key) != CRYPT_OK)) continue;
       }
-
-      cur_len = remaining;
-      if ((err = ssh_decode_sequence_multi(p, &cur_len,
-                                           LTC_SSHDATA_MPINT, key->u.rsa.N,
-                                           LTC_SSHDATA_MPINT, key->u.rsa.e,
-                                           LTC_SSHDATA_MPINT, key->u.rsa.d,
-                                           LTC_SSHDATA_MPINT, key->u.rsa.qP,
-                                           LTC_SSHDATA_MPINT, key->u.rsa.q,
-                                           LTC_SSHDATA_MPINT, key->u.rsa.p,
-                                           LTC_SSHDATA_EOL)) != CRYPT_OK) {
+      if ((err = ssh_pkas[n].decode(p, &cur_len, key)) != CRYPT_OK) {
          die(err);
       }
-
-      if ((err = mp_sub_d(key->u.rsa.p, 1,  tmp1)) != CRYPT_OK)                     { die(err); } /* tmp1 = q-1 */
-      if ((err = mp_sub_d(key->u.rsa.q, 1,  tmp2)) != CRYPT_OK)                     { die(err); } /* tmp2 = p-1 */
-      if ((err = mp_mod( key->u.rsa.d,  tmp1,  key->u.rsa.dP)) != CRYPT_OK)         { die(err); } /* dP = d mod p-1 */
-      if ((err = mp_mod( key->u.rsa.d,  tmp2,  key->u.rsa.dQ)) != CRYPT_OK)         { die(err); } /* dQ = d mod q-1 */
-
-      mp_clear_multi(tmp2, tmp1, NULL);
-   } else {
-      DIE("unsupported pka");
+      break;
    }
+   if (n == sizeof(ssh_pkas)/sizeof(ssh_pkas[0])) DIE("unsupported pka %s", pka);
+
    p += cur_len;
    remaining -= cur_len;
-
    cur_len = remaining;
+
    if ((err = ssh_decode_sequence_multi(p, &cur_len,
                                         LTC_SSHDATA_STRING, comment, &commentlen,
                                         LTC_SSHDATA_EOL)) != CRYPT_OK) {