diff options
Diffstat (limited to 'key.c')
-rw-r--r-- | key.c | 291 |
1 files changed, 126 insertions, 165 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.c,v 1.100 2013/01/17 23:00:01 djm Exp $ */ | 1 | /* $OpenBSD: key.c,v 1.104 2013/05/19 02:42:42 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * read_bignum(): | 3 | * read_bignum(): |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -187,14 +187,13 @@ cert_free(struct KeyCert *cert) | |||
187 | buffer_free(&cert->certblob); | 187 | buffer_free(&cert->certblob); |
188 | buffer_free(&cert->critical); | 188 | buffer_free(&cert->critical); |
189 | buffer_free(&cert->extensions); | 189 | buffer_free(&cert->extensions); |
190 | if (cert->key_id != NULL) | 190 | free(cert->key_id); |
191 | xfree(cert->key_id); | ||
192 | for (i = 0; i < cert->nprincipals; i++) | 191 | for (i = 0; i < cert->nprincipals; i++) |
193 | xfree(cert->principals[i]); | 192 | free(cert->principals[i]); |
194 | if (cert->principals != NULL) | 193 | free(cert->principals); |
195 | xfree(cert->principals); | ||
196 | if (cert->signature_key != NULL) | 194 | if (cert->signature_key != NULL) |
197 | key_free(cert->signature_key); | 195 | key_free(cert->signature_key); |
196 | free(cert); | ||
198 | } | 197 | } |
199 | 198 | ||
200 | void | 199 | void |
@@ -238,7 +237,7 @@ key_free(Key *k) | |||
238 | k->cert = NULL; | 237 | k->cert = NULL; |
239 | } | 238 | } |
240 | 239 | ||
241 | xfree(k); | 240 | free(k); |
242 | } | 241 | } |
243 | 242 | ||
244 | static int | 243 | static int |
@@ -388,7 +387,7 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type, | |||
388 | EVP_DigestUpdate(&ctx, blob, len); | 387 | EVP_DigestUpdate(&ctx, blob, len); |
389 | EVP_DigestFinal(&ctx, retval, dgst_raw_length); | 388 | EVP_DigestFinal(&ctx, retval, dgst_raw_length); |
390 | memset(blob, 0, len); | 389 | memset(blob, 0, len); |
391 | xfree(blob); | 390 | free(blob); |
392 | } else { | 391 | } else { |
393 | fatal("key_fingerprint_raw: blob is null"); | 392 | fatal("key_fingerprint_raw: blob is null"); |
394 | } | 393 | } |
@@ -570,7 +569,7 @@ key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k) | |||
570 | } | 569 | } |
571 | 570 | ||
572 | char * | 571 | char * |
573 | key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) | 572 | key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) |
574 | { | 573 | { |
575 | char *retval = NULL; | 574 | char *retval = NULL; |
576 | u_char *dgst_raw; | 575 | u_char *dgst_raw; |
@@ -595,7 +594,7 @@ key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) | |||
595 | break; | 594 | break; |
596 | } | 595 | } |
597 | memset(dgst_raw, 0, dgst_raw_len); | 596 | memset(dgst_raw, 0, dgst_raw_len); |
598 | xfree(dgst_raw); | 597 | free(dgst_raw); |
599 | return retval; | 598 | return retval; |
600 | } | 599 | } |
601 | 600 | ||
@@ -740,11 +739,11 @@ key_read(Key *ret, char **cpp) | |||
740 | n = uudecode(cp, blob, len); | 739 | n = uudecode(cp, blob, len); |
741 | if (n < 0) { | 740 | if (n < 0) { |
742 | error("key_read: uudecode %s failed", cp); | 741 | error("key_read: uudecode %s failed", cp); |
743 | xfree(blob); | 742 | free(blob); |
744 | return -1; | 743 | return -1; |
745 | } | 744 | } |
746 | k = key_from_blob(blob, (u_int)n); | 745 | k = key_from_blob(blob, (u_int)n); |
747 | xfree(blob); | 746 | free(blob); |
748 | if (k == NULL) { | 747 | if (k == NULL) { |
749 | error("key_read: key_from_blob %s failed", cp); | 748 | error("key_read: key_from_blob %s failed", cp); |
750 | return -1; | 749 | return -1; |
@@ -885,43 +884,13 @@ key_write(const Key *key, FILE *f) | |||
885 | fprintf(f, "%s %s", key_ssh_name(key), uu); | 884 | fprintf(f, "%s %s", key_ssh_name(key), uu); |
886 | success = 1; | 885 | success = 1; |
887 | } | 886 | } |
888 | xfree(blob); | 887 | free(blob); |
889 | xfree(uu); | 888 | free(uu); |
890 | 889 | ||
891 | return success; | 890 | return success; |
892 | } | 891 | } |
893 | 892 | ||
894 | const char * | 893 | const char * |
895 | key_type(const Key *k) | ||
896 | { | ||
897 | switch (k->type) { | ||
898 | case KEY_RSA1: | ||
899 | return "RSA1"; | ||
900 | case KEY_RSA: | ||
901 | return "RSA"; | ||
902 | case KEY_DSA: | ||
903 | return "DSA"; | ||
904 | #ifdef OPENSSL_HAS_ECC | ||
905 | case KEY_ECDSA: | ||
906 | return "ECDSA"; | ||
907 | #endif | ||
908 | case KEY_RSA_CERT_V00: | ||
909 | return "RSA-CERT-V00"; | ||
910 | case KEY_DSA_CERT_V00: | ||
911 | return "DSA-CERT-V00"; | ||
912 | case KEY_RSA_CERT: | ||
913 | return "RSA-CERT"; | ||
914 | case KEY_DSA_CERT: | ||
915 | return "DSA-CERT"; | ||
916 | #ifdef OPENSSL_HAS_ECC | ||
917 | case KEY_ECDSA_CERT: | ||
918 | return "ECDSA-CERT"; | ||
919 | #endif | ||
920 | } | ||
921 | return "unknown"; | ||
922 | } | ||
923 | |||
924 | const char * | ||
925 | key_cert_type(const Key *k) | 894 | key_cert_type(const Key *k) |
926 | { | 895 | { |
927 | switch (k->cert->type) { | 896 | switch (k->cert->type) { |
@@ -934,50 +903,60 @@ key_cert_type(const Key *k) | |||
934 | } | 903 | } |
935 | } | 904 | } |
936 | 905 | ||
906 | struct keytype { | ||
907 | char *name; | ||
908 | char *shortname; | ||
909 | int type; | ||
910 | int nid; | ||
911 | int cert; | ||
912 | }; | ||
913 | static const struct keytype keytypes[] = { | ||
914 | { NULL, "RSA1", KEY_RSA1, 0, 0 }, | ||
915 | { "ssh-rsa", "RSA", KEY_RSA, 0, 0 }, | ||
916 | { "ssh-dss", "DSA", KEY_DSA, 0, 0 }, | ||
917 | #ifdef OPENSSL_HAS_ECC | ||
918 | { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 }, | ||
919 | { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 }, | ||
920 | { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 }, | ||
921 | #endif /* OPENSSL_HAS_ECC */ | ||
922 | { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 }, | ||
923 | { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 }, | ||
924 | #ifdef OPENSSL_HAS_ECC | ||
925 | { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", | ||
926 | KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 }, | ||
927 | { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", | ||
928 | KEY_ECDSA_CERT, NID_secp384r1, 1 }, | ||
929 | { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", | ||
930 | KEY_ECDSA_CERT, NID_secp521r1, 1 }, | ||
931 | #endif /* OPENSSL_HAS_ECC */ | ||
932 | { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00", | ||
933 | KEY_RSA_CERT_V00, 0, 1 }, | ||
934 | { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", | ||
935 | KEY_DSA_CERT_V00, 0, 1 }, | ||
936 | { "null", "null", KEY_NULL, 0, 0 }, | ||
937 | { NULL, NULL, -1, -1, 0 } | ||
938 | }; | ||
939 | |||
940 | const char * | ||
941 | key_type(const Key *k) | ||
942 | { | ||
943 | const struct keytype *kt; | ||
944 | |||
945 | for (kt = keytypes; kt->type != -1; kt++) { | ||
946 | if (kt->type == k->type) | ||
947 | return kt->shortname; | ||
948 | } | ||
949 | return "unknown"; | ||
950 | } | ||
951 | |||
937 | static const char * | 952 | static const char * |
938 | key_ssh_name_from_type_nid(int type, int nid) | 953 | key_ssh_name_from_type_nid(int type, int nid) |
939 | { | 954 | { |
940 | switch (type) { | 955 | const struct keytype *kt; |
941 | case KEY_RSA: | 956 | |
942 | return "ssh-rsa"; | 957 | for (kt = keytypes; kt->type != -1; kt++) { |
943 | case KEY_DSA: | 958 | if (kt->type == type && (kt->nid == 0 || kt->nid == nid)) |
944 | return "ssh-dss"; | 959 | return kt->name; |
945 | case KEY_RSA_CERT_V00: | ||
946 | return "ssh-rsa-cert-v00@openssh.com"; | ||
947 | case KEY_DSA_CERT_V00: | ||
948 | return "ssh-dss-cert-v00@openssh.com"; | ||
949 | case KEY_RSA_CERT: | ||
950 | return "ssh-rsa-cert-v01@openssh.com"; | ||
951 | case KEY_DSA_CERT: | ||
952 | return "ssh-dss-cert-v01@openssh.com"; | ||
953 | #ifdef OPENSSL_HAS_ECC | ||
954 | case KEY_ECDSA: | ||
955 | switch (nid) { | ||
956 | case NID_X9_62_prime256v1: | ||
957 | return "ecdsa-sha2-nistp256"; | ||
958 | case NID_secp384r1: | ||
959 | return "ecdsa-sha2-nistp384"; | ||
960 | case NID_secp521r1: | ||
961 | return "ecdsa-sha2-nistp521"; | ||
962 | default: | ||
963 | break; | ||
964 | } | ||
965 | break; | ||
966 | case KEY_ECDSA_CERT: | ||
967 | switch (nid) { | ||
968 | case NID_X9_62_prime256v1: | ||
969 | return "ecdsa-sha2-nistp256-cert-v01@openssh.com"; | ||
970 | case NID_secp384r1: | ||
971 | return "ecdsa-sha2-nistp384-cert-v01@openssh.com"; | ||
972 | case NID_secp521r1: | ||
973 | return "ecdsa-sha2-nistp521-cert-v01@openssh.com"; | ||
974 | default: | ||
975 | break; | ||
976 | } | ||
977 | break; | ||
978 | #endif /* OPENSSL_HAS_ECC */ | ||
979 | case KEY_NULL: | ||
980 | return "null"; | ||
981 | } | 960 | } |
982 | return "ssh-unknown"; | 961 | return "ssh-unknown"; |
983 | } | 962 | } |
@@ -995,6 +974,56 @@ key_ssh_name_plain(const Key *k) | |||
995 | k->ecdsa_nid); | 974 | k->ecdsa_nid); |
996 | } | 975 | } |
997 | 976 | ||
977 | int | ||
978 | key_type_from_name(char *name) | ||
979 | { | ||
980 | const struct keytype *kt; | ||
981 | |||
982 | for (kt = keytypes; kt->type != -1; kt++) { | ||
983 | /* Only allow shortname matches for plain key types */ | ||
984 | if ((kt->name != NULL && strcmp(name, kt->name) == 0) || | ||
985 | (!kt->cert && strcasecmp(kt->shortname, name) == 0)) | ||
986 | return kt->type; | ||
987 | } | ||
988 | debug2("key_type_from_name: unknown key type '%s'", name); | ||
989 | return KEY_UNSPEC; | ||
990 | } | ||
991 | |||
992 | int | ||
993 | key_ecdsa_nid_from_name(const char *name) | ||
994 | { | ||
995 | const struct keytype *kt; | ||
996 | |||
997 | for (kt = keytypes; kt->type != -1; kt++) { | ||
998 | if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) | ||
999 | continue; | ||
1000 | if (kt->name != NULL && strcmp(name, kt->name) == 0) | ||
1001 | return kt->nid; | ||
1002 | } | ||
1003 | debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name); | ||
1004 | return -1; | ||
1005 | } | ||
1006 | |||
1007 | char * | ||
1008 | key_alg_list(void) | ||
1009 | { | ||
1010 | char *ret = NULL; | ||
1011 | size_t nlen, rlen = 0; | ||
1012 | const struct keytype *kt; | ||
1013 | |||
1014 | for (kt = keytypes; kt->type != -1; kt++) { | ||
1015 | if (kt->name == NULL) | ||
1016 | continue; | ||
1017 | if (ret != NULL) | ||
1018 | ret[rlen++] = '\n'; | ||
1019 | nlen = strlen(kt->name); | ||
1020 | ret = xrealloc(ret, 1, rlen + nlen + 2); | ||
1021 | memcpy(ret + rlen, kt->name, nlen + 1); | ||
1022 | rlen += nlen; | ||
1023 | } | ||
1024 | return ret; | ||
1025 | } | ||
1026 | |||
998 | u_int | 1027 | u_int |
999 | key_size(const Key *k) | 1028 | key_size(const Key *k) |
1000 | { | 1029 | { |
@@ -1250,67 +1279,6 @@ key_from_private(const Key *k) | |||
1250 | } | 1279 | } |
1251 | 1280 | ||
1252 | int | 1281 | int |
1253 | key_type_from_name(char *name) | ||
1254 | { | ||
1255 | if (strcmp(name, "rsa1") == 0) { | ||
1256 | return KEY_RSA1; | ||
1257 | } else if (strcmp(name, "rsa") == 0) { | ||
1258 | return KEY_RSA; | ||
1259 | } else if (strcmp(name, "dsa") == 0) { | ||
1260 | return KEY_DSA; | ||
1261 | } else if (strcmp(name, "ssh-rsa") == 0) { | ||
1262 | return KEY_RSA; | ||
1263 | } else if (strcmp(name, "ssh-dss") == 0) { | ||
1264 | return KEY_DSA; | ||
1265 | #ifdef OPENSSL_HAS_ECC | ||
1266 | } else if (strcmp(name, "ecdsa") == 0 || | ||
1267 | strcmp(name, "ecdsa-sha2-nistp256") == 0 || | ||
1268 | strcmp(name, "ecdsa-sha2-nistp384") == 0 || | ||
1269 | strcmp(name, "ecdsa-sha2-nistp521") == 0) { | ||
1270 | return KEY_ECDSA; | ||
1271 | #endif | ||
1272 | } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) { | ||
1273 | return KEY_RSA_CERT_V00; | ||
1274 | } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) { | ||
1275 | return KEY_DSA_CERT_V00; | ||
1276 | } else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) { | ||
1277 | return KEY_RSA_CERT; | ||
1278 | } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) { | ||
1279 | return KEY_DSA_CERT; | ||
1280 | #ifdef OPENSSL_HAS_ECC | ||
1281 | } else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0 || | ||
1282 | strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0 || | ||
1283 | strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) { | ||
1284 | return KEY_ECDSA_CERT; | ||
1285 | #endif | ||
1286 | } else if (strcmp(name, "null") == 0) { | ||
1287 | return KEY_NULL; | ||
1288 | } | ||
1289 | |||
1290 | debug2("key_type_from_name: unknown key type '%s'", name); | ||
1291 | return KEY_UNSPEC; | ||
1292 | } | ||
1293 | |||
1294 | int | ||
1295 | key_ecdsa_nid_from_name(const char *name) | ||
1296 | { | ||
1297 | #ifdef OPENSSL_HAS_ECC | ||
1298 | if (strcmp(name, "ecdsa-sha2-nistp256") == 0 || | ||
1299 | strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0) | ||
1300 | return NID_X9_62_prime256v1; | ||
1301 | if (strcmp(name, "ecdsa-sha2-nistp384") == 0 || | ||
1302 | strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0) | ||
1303 | return NID_secp384r1; | ||
1304 | if (strcmp(name, "ecdsa-sha2-nistp521") == 0 || | ||
1305 | strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) | ||
1306 | return NID_secp521r1; | ||
1307 | #endif /* OPENSSL_HAS_ECC */ | ||
1308 | |||
1309 | debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name); | ||
1310 | return -1; | ||
1311 | } | ||
1312 | |||
1313 | int | ||
1314 | key_names_valid2(const char *names) | 1282 | key_names_valid2(const char *names) |
1315 | { | 1283 | { |
1316 | char *s, *cp, *p; | 1284 | char *s, *cp, *p; |
@@ -1323,12 +1291,12 @@ key_names_valid2(const char *names) | |||
1323 | switch (key_type_from_name(p)) { | 1291 | switch (key_type_from_name(p)) { |
1324 | case KEY_RSA1: | 1292 | case KEY_RSA1: |
1325 | case KEY_UNSPEC: | 1293 | case KEY_UNSPEC: |
1326 | xfree(s); | 1294 | free(s); |
1327 | return 0; | 1295 | return 0; |
1328 | } | 1296 | } |
1329 | } | 1297 | } |
1330 | debug3("key names ok: [%s]", names); | 1298 | debug3("key names ok: [%s]", names); |
1331 | xfree(s); | 1299 | free(s); |
1332 | return 1; | 1300 | return 1; |
1333 | } | 1301 | } |
1334 | 1302 | ||
@@ -1450,16 +1418,11 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) | |||
1450 | 1418 | ||
1451 | out: | 1419 | out: |
1452 | buffer_free(&tmp); | 1420 | buffer_free(&tmp); |
1453 | if (principals != NULL) | 1421 | free(principals); |
1454 | xfree(principals); | 1422 | free(critical); |
1455 | if (critical != NULL) | 1423 | free(exts); |
1456 | xfree(critical); | 1424 | free(sig_key); |
1457 | if (exts != NULL) | 1425 | free(sig); |
1458 | xfree(exts); | ||
1459 | if (sig_key != NULL) | ||
1460 | xfree(sig_key); | ||
1461 | if (sig != NULL) | ||
1462 | xfree(sig); | ||
1463 | return ret; | 1426 | return ret; |
1464 | } | 1427 | } |
1465 | 1428 | ||
@@ -1579,10 +1542,8 @@ key_from_blob(const u_char *blob, u_int blen) | |||
1579 | if (key != NULL && rlen != 0) | 1542 | if (key != NULL && rlen != 0) |
1580 | error("key_from_blob: remaining bytes in key blob %d", rlen); | 1543 | error("key_from_blob: remaining bytes in key blob %d", rlen); |
1581 | out: | 1544 | out: |
1582 | if (ktype != NULL) | 1545 | free(ktype); |
1583 | xfree(ktype); | 1546 | free(curve); |
1584 | if (curve != NULL) | ||
1585 | xfree(curve); | ||
1586 | #ifdef OPENSSL_HAS_ECC | 1547 | #ifdef OPENSSL_HAS_ECC |
1587 | if (q != NULL) | 1548 | if (q != NULL) |
1588 | EC_POINT_free(q); | 1549 | EC_POINT_free(q); |
@@ -1932,7 +1893,7 @@ key_certify(Key *k, Key *ca) | |||
1932 | default: | 1893 | default: |
1933 | error("%s: key has incorrect type %s", __func__, key_type(k)); | 1894 | error("%s: key has incorrect type %s", __func__, key_type(k)); |
1934 | buffer_clear(&k->cert->certblob); | 1895 | buffer_clear(&k->cert->certblob); |
1935 | xfree(ca_blob); | 1896 | free(ca_blob); |
1936 | return -1; | 1897 | return -1; |
1937 | } | 1898 | } |
1938 | 1899 | ||
@@ -1968,7 +1929,7 @@ key_certify(Key *k, Key *ca) | |||
1968 | 1929 | ||
1969 | buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */ | 1930 | buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */ |
1970 | buffer_put_string(&k->cert->certblob, ca_blob, ca_len); | 1931 | buffer_put_string(&k->cert->certblob, ca_blob, ca_len); |
1971 | xfree(ca_blob); | 1932 | free(ca_blob); |
1972 | 1933 | ||
1973 | /* Sign the whole mess */ | 1934 | /* Sign the whole mess */ |
1974 | if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob), | 1935 | if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob), |
@@ -1979,7 +1940,7 @@ key_certify(Key *k, Key *ca) | |||
1979 | } | 1940 | } |
1980 | /* Append signature and we are done */ | 1941 | /* Append signature and we are done */ |
1981 | buffer_put_string(&k->cert->certblob, sig_blob, sig_len); | 1942 | buffer_put_string(&k->cert->certblob, sig_blob, sig_len); |
1982 | xfree(sig_blob); | 1943 | free(sig_blob); |
1983 | 1944 | ||
1984 | return 0; | 1945 | return 0; |
1985 | } | 1946 | } |