summaryrefslogtreecommitdiff
path: root/ssh-pkcs11.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-pkcs11.c')
-rw-r--r--ssh-pkcs11.c142
1 files changed, 89 insertions, 53 deletions
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index 09f1ea347..a302c79c0 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11.c,v 1.46 2019/10/01 10:22:53 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11.c,v 1.47 2020/01/25 00:03:36 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved. 4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
@@ -893,15 +893,16 @@ fail:
893 return (key); 893 return (key);
894} 894}
895 895
896static struct sshkey * 896static int
897pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, 897pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
898 CK_OBJECT_HANDLE *obj) 898 CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp)
899{ 899{
900 CK_ATTRIBUTE cert_attr[3]; 900 CK_ATTRIBUTE cert_attr[3];
901 CK_SESSION_HANDLE session; 901 CK_SESSION_HANDLE session;
902 CK_FUNCTION_LIST *f = NULL; 902 CK_FUNCTION_LIST *f = NULL;
903 CK_RV rv; 903 CK_RV rv;
904 X509 *x509 = NULL; 904 X509 *x509 = NULL;
905 X509_NAME *x509_name = NULL;
905 EVP_PKEY *evp; 906 EVP_PKEY *evp;
906 RSA *rsa = NULL; 907 RSA *rsa = NULL;
907#ifdef OPENSSL_HAS_ECC 908#ifdef OPENSSL_HAS_ECC
@@ -912,7 +913,11 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
912#ifdef HAVE_EC_KEY_METHOD_NEW 913#ifdef HAVE_EC_KEY_METHOD_NEW
913 int nid; 914 int nid;
914#endif 915#endif
915 const u_char *cp; 916 const u_char *cp;
917 char *subject = NULL;
918
919 *keyp = NULL;
920 *labelp = NULL;
916 921
917 memset(&cert_attr, 0, sizeof(cert_attr)); 922 memset(&cert_attr, 0, sizeof(cert_attr));
918 cert_attr[0].type = CKA_ID; 923 cert_attr[0].type = CKA_ID;
@@ -926,7 +931,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
926 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); 931 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
927 if (rv != CKR_OK) { 932 if (rv != CKR_OK) {
928 error("C_GetAttributeValue failed: %lu", rv); 933 error("C_GetAttributeValue failed: %lu", rv);
929 return (NULL); 934 return -1;
930 } 935 }
931 936
932 /* 937 /*
@@ -937,7 +942,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
937 if (cert_attr[1].ulValueLen == 0 || 942 if (cert_attr[1].ulValueLen == 0 ||
938 cert_attr[2].ulValueLen == 0) { 943 cert_attr[2].ulValueLen == 0) {
939 error("invalid attribute length"); 944 error("invalid attribute length");
940 return (NULL); 945 return -1;
941 } 946 }
942 947
943 /* allocate buffers for attributes */ 948 /* allocate buffers for attributes */
@@ -949,44 +954,45 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
949 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); 954 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
950 if (rv != CKR_OK) { 955 if (rv != CKR_OK) {
951 error("C_GetAttributeValue failed: %lu", rv); 956 error("C_GetAttributeValue failed: %lu", rv);
952 goto fail; 957 goto out;
953 } 958 }
954 959
955 x509 = X509_new(); 960 /* Decode DER-encoded cert subject */
956 if (x509 == NULL) { 961 cp = cert_attr[2].pValue;
957 error("x509_new failed"); 962 if ((x509_name = d2i_X509_NAME(NULL, &cp,
958 goto fail; 963 cert_attr[1].ulValueLen)) == NULL ||
959 } 964 (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL)
965 subject = xstrdup("invalid subject");
966 X509_NAME_free(x509_name);
960 967
961 cp = cert_attr[2].pValue; 968 cp = cert_attr[2].pValue;
962 if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) { 969 if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) {
963 error("d2i_x509 failed"); 970 error("d2i_x509 failed");
964 goto fail; 971 goto out;
965 } 972 }
966 973
967 evp = X509_get_pubkey(x509); 974 if ((evp = X509_get_pubkey(x509)) == NULL) {
968 if (evp == NULL) {
969 error("X509_get_pubkey failed"); 975 error("X509_get_pubkey failed");
970 goto fail; 976 goto out;
971 } 977 }
972 978
973 if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) { 979 if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
974 if (EVP_PKEY_get0_RSA(evp) == NULL) { 980 if (EVP_PKEY_get0_RSA(evp) == NULL) {
975 error("invalid x509; no rsa key"); 981 error("invalid x509; no rsa key");
976 goto fail; 982 goto out;
977 } 983 }
978 if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) { 984 if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
979 error("RSAPublicKey_dup failed"); 985 error("RSAPublicKey_dup failed");
980 goto fail; 986 goto out;
981 } 987 }
982 988
983 if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) 989 if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))
984 goto fail; 990 goto out;
985 991
986 key = sshkey_new(KEY_UNSPEC); 992 key = sshkey_new(KEY_UNSPEC);
987 if (key == NULL) { 993 if (key == NULL) {
988 error("sshkey_new failed"); 994 error("sshkey_new failed");
989 goto fail; 995 goto out;
990 } 996 }
991 997
992 key->rsa = rsa; 998 key->rsa = rsa;
@@ -997,26 +1003,26 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
997 } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) { 1003 } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
998 if (EVP_PKEY_get0_EC_KEY(evp) == NULL) { 1004 if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
999 error("invalid x509; no ec key"); 1005 error("invalid x509; no ec key");
1000 goto fail; 1006 goto out;
1001 } 1007 }
1002 if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) { 1008 if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
1003 error("EC_KEY_dup failed"); 1009 error("EC_KEY_dup failed");
1004 goto fail; 1010 goto out;
1005 } 1011 }
1006 1012
1007 nid = sshkey_ecdsa_key_to_nid(ec); 1013 nid = sshkey_ecdsa_key_to_nid(ec);
1008 if (nid < 0) { 1014 if (nid < 0) {
1009 error("couldn't get curve nid"); 1015 error("couldn't get curve nid");
1010 goto fail; 1016 goto out;
1011 } 1017 }
1012 1018
1013 if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) 1019 if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))
1014 goto fail; 1020 goto out;
1015 1021
1016 key = sshkey_new(KEY_UNSPEC); 1022 key = sshkey_new(KEY_UNSPEC);
1017 if (key == NULL) { 1023 if (key == NULL) {
1018 error("sshkey_new failed"); 1024 error("sshkey_new failed");
1019 goto fail; 1025 goto out;
1020 } 1026 }
1021 1027
1022 key->ecdsa = ec; 1028 key->ecdsa = ec;
@@ -1025,10 +1031,11 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
1025 key->flags |= SSHKEY_FLAG_EXT; 1031 key->flags |= SSHKEY_FLAG_EXT;
1026 ec = NULL; /* now owned by key */ 1032 ec = NULL; /* now owned by key */
1027#endif /* HAVE_EC_KEY_METHOD_NEW */ 1033#endif /* HAVE_EC_KEY_METHOD_NEW */
1028 } else 1034 } else {
1029 error("unknown certificate key type"); 1035 error("unknown certificate key type");
1030 1036 goto out;
1031fail: 1037 }
1038 out:
1032 for (i = 0; i < 3; i++) 1039 for (i = 0; i < 3; i++)
1033 free(cert_attr[i].pValue); 1040 free(cert_attr[i].pValue);
1034 X509_free(x509); 1041 X509_free(x509);
@@ -1036,8 +1043,14 @@ fail:
1036#ifdef OPENSSL_HAS_ECC 1043#ifdef OPENSSL_HAS_ECC
1037 EC_KEY_free(ec); 1044 EC_KEY_free(ec);
1038#endif 1045#endif
1039 1046 if (key == NULL) {
1040 return (key); 1047 free(subject);
1048 return -1;
1049 }
1050 /* success */
1051 *keyp = key;
1052 *labelp = subject;
1053 return 0;
1041} 1054}
1042 1055
1043#if 0 1056#if 0
@@ -1058,7 +1071,7 @@ have_rsa_key(const RSA *rsa)
1058 */ 1071 */
1059static int 1072static int
1060pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, 1073pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1061 struct sshkey ***keysp, int *nkeys) 1074 struct sshkey ***keysp, char ***labelsp, int *nkeys)
1062{ 1075{
1063 struct sshkey *key = NULL; 1076 struct sshkey *key = NULL;
1064 CK_OBJECT_CLASS key_class; 1077 CK_OBJECT_CLASS key_class;
@@ -1069,6 +1082,7 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1069 CK_OBJECT_HANDLE obj; 1082 CK_OBJECT_HANDLE obj;
1070 CK_ULONG n = 0; 1083 CK_ULONG n = 0;
1071 int ret = -1; 1084 int ret = -1;
1085 char *label;
1072 1086
1073 memset(&key_attr, 0, sizeof(key_attr)); 1087 memset(&key_attr, 0, sizeof(key_attr));
1074 memset(&obj, 0, sizeof(obj)); 1088 memset(&obj, 0, sizeof(obj));
@@ -1110,18 +1124,19 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1110 goto fail; 1124 goto fail;
1111 } 1125 }
1112 1126
1127 key = NULL;
1128 label = NULL;
1113 switch (ck_cert_type) { 1129 switch (ck_cert_type) {
1114 case CKC_X_509: 1130 case CKC_X_509:
1115 key = pkcs11_fetch_x509_pubkey(p, slotidx, &obj); 1131 if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj,
1132 &key, &label) != 0) {
1133 error("failed to fetch key");
1134 continue;
1135 }
1116 break; 1136 break;
1117 default: 1137 default:
1118 /* XXX print key type? */ 1138 error("skipping unsupported certificate type %lu",
1119 key = NULL; 1139 ck_cert_type);
1120 error("skipping unsupported certificate type");
1121 }
1122
1123 if (key == NULL) {
1124 error("failed to fetch key");
1125 continue; 1140 continue;
1126 } 1141 }
1127 1142
@@ -1132,6 +1147,11 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1132 *keysp = xrecallocarray(*keysp, *nkeys, 1147 *keysp = xrecallocarray(*keysp, *nkeys,
1133 *nkeys + 1, sizeof(struct sshkey *)); 1148 *nkeys + 1, sizeof(struct sshkey *));
1134 (*keysp)[*nkeys] = key; 1149 (*keysp)[*nkeys] = key;
1150 if (labelsp != NULL) {
1151 *labelsp = xrecallocarray(*labelsp, *nkeys,
1152 *nkeys + 1, sizeof(char *));
1153 (*labelsp)[*nkeys] = xstrdup((char *)label);
1154 }
1135 *nkeys = *nkeys + 1; 1155 *nkeys = *nkeys + 1;
1136 debug("have %d keys", *nkeys); 1156 debug("have %d keys", *nkeys);
1137 } 1157 }
@@ -1155,11 +1175,11 @@ fail:
1155 */ 1175 */
1156static int 1176static int
1157pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, 1177pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1158 struct sshkey ***keysp, int *nkeys) 1178 struct sshkey ***keysp, char ***labelsp, int *nkeys)
1159{ 1179{
1160 struct sshkey *key = NULL; 1180 struct sshkey *key = NULL;
1161 CK_OBJECT_CLASS key_class; 1181 CK_OBJECT_CLASS key_class;
1162 CK_ATTRIBUTE key_attr[1]; 1182 CK_ATTRIBUTE key_attr[2];
1163 CK_SESSION_HANDLE session; 1183 CK_SESSION_HANDLE session;
1164 CK_FUNCTION_LIST *f = NULL; 1184 CK_FUNCTION_LIST *f = NULL;
1165 CK_RV rv; 1185 CK_RV rv;
@@ -1186,6 +1206,7 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1186 1206
1187 while (1) { 1207 while (1) {
1188 CK_KEY_TYPE ck_key_type; 1208 CK_KEY_TYPE ck_key_type;
1209 CK_UTF8CHAR label[256];
1189 1210
1190 rv = f->C_FindObjects(session, &obj, 1, &n); 1211 rv = f->C_FindObjects(session, &obj, 1, &n);
1191 if (rv != CKR_OK) { 1212 if (rv != CKR_OK) {
@@ -1200,13 +1221,18 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1200 key_attr[0].type = CKA_KEY_TYPE; 1221 key_attr[0].type = CKA_KEY_TYPE;
1201 key_attr[0].pValue = &ck_key_type; 1222 key_attr[0].pValue = &ck_key_type;
1202 key_attr[0].ulValueLen = sizeof(ck_key_type); 1223 key_attr[0].ulValueLen = sizeof(ck_key_type);
1224 key_attr[1].type = CKA_LABEL;
1225 key_attr[1].pValue = &label;
1226 key_attr[1].ulValueLen = sizeof(label) - 1;
1203 1227
1204 rv = f->C_GetAttributeValue(session, obj, key_attr, 1); 1228 rv = f->C_GetAttributeValue(session, obj, key_attr, 2);
1205 if (rv != CKR_OK) { 1229 if (rv != CKR_OK) {
1206 error("C_GetAttributeValue failed: %lu", rv); 1230 error("C_GetAttributeValue failed: %lu", rv);
1207 goto fail; 1231 goto fail;
1208 } 1232 }
1209 1233
1234 label[key_attr[1].ulValueLen] = '\0';
1235
1210 switch (ck_key_type) { 1236 switch (ck_key_type) {
1211 case CKK_RSA: 1237 case CKK_RSA:
1212 key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); 1238 key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
@@ -1234,6 +1260,11 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1234 *keysp = xrecallocarray(*keysp, *nkeys, 1260 *keysp = xrecallocarray(*keysp, *nkeys,
1235 *nkeys + 1, sizeof(struct sshkey *)); 1261 *nkeys + 1, sizeof(struct sshkey *));
1236 (*keysp)[*nkeys] = key; 1262 (*keysp)[*nkeys] = key;
1263 if (labelsp != NULL) {
1264 *labelsp = xrecallocarray(*labelsp, *nkeys,
1265 *nkeys + 1, sizeof(char *));
1266 (*labelsp)[*nkeys] = xstrdup((char *)label);
1267 }
1237 *nkeys = *nkeys + 1; 1268 *nkeys = *nkeys + 1;
1238 debug("have %d keys", *nkeys); 1269 debug("have %d keys", *nkeys);
1239 } 1270 }
@@ -1440,7 +1471,8 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1440 * keyp is provided, fetch keys. 1471 * keyp is provided, fetch keys.
1441 */ 1472 */
1442static int 1473static int
1443pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, 1474pkcs11_register_provider(char *provider_id, char *pin,
1475 struct sshkey ***keyp, char ***labelsp,
1444 struct pkcs11_provider **providerp, CK_ULONG user) 1476 struct pkcs11_provider **providerp, CK_ULONG user)
1445{ 1477{
1446 int nkeys, need_finalize = 0; 1478 int nkeys, need_finalize = 0;
@@ -1459,6 +1491,8 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1459 1491
1460 if (keyp != NULL) 1492 if (keyp != NULL)
1461 *keyp = NULL; 1493 *keyp = NULL;
1494 if (labelsp != NULL)
1495 *labelsp = NULL;
1462 1496
1463 if (pkcs11_provider_lookup(provider_id) != NULL) { 1497 if (pkcs11_provider_lookup(provider_id) != NULL) {
1464 debug("%s: provider already registered: %s", 1498 debug("%s: provider already registered: %s",
@@ -1556,8 +1590,8 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1556 if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || 1590 if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 ||
1557 keyp == NULL) 1591 keyp == NULL)
1558 continue; 1592 continue;
1559 pkcs11_fetch_keys(p, i, keyp, &nkeys); 1593 pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1560 pkcs11_fetch_certs(p, i, keyp, &nkeys); 1594 pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1561 if (nkeys == 0 && !p->slotinfo[i].logged_in && 1595 if (nkeys == 0 && !p->slotinfo[i].logged_in &&
1562 pkcs11_interactive) { 1596 pkcs11_interactive) {
1563 /* 1597 /*
@@ -1569,8 +1603,8 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1569 error("login failed"); 1603 error("login failed");
1570 continue; 1604 continue;
1571 } 1605 }
1572 pkcs11_fetch_keys(p, i, keyp, &nkeys); 1606 pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1573 pkcs11_fetch_certs(p, i, keyp, &nkeys); 1607 pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1574 } 1608 }
1575 } 1609 }
1576 1610
@@ -1601,12 +1635,14 @@ fail:
1601 * fails if provider already exists 1635 * fails if provider already exists
1602 */ 1636 */
1603int 1637int
1604pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) 1638pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1639 char ***labelsp)
1605{ 1640{
1606 struct pkcs11_provider *p = NULL; 1641 struct pkcs11_provider *p = NULL;
1607 int nkeys; 1642 int nkeys;
1608 1643
1609 nkeys = pkcs11_register_provider(provider_id, pin, keyp, &p, CKU_USER); 1644 nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
1645 &p, CKU_USER);
1610 1646
1611 /* no keys found or some other error, de-register provider */ 1647 /* no keys found or some other error, de-register provider */
1612 if (nkeys <= 0 && p != NULL) { 1648 if (nkeys <= 0 && p != NULL) {
@@ -1638,8 +1674,8 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
1638 1674
1639 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) 1675 if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
1640 debug("%s: provider \"%s\" available", __func__, provider_id); 1676 debug("%s: provider \"%s\" available", __func__, provider_id);
1641 else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, &p, 1677 else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL,
1642 CKU_SO)) < 0) { 1678 &p, CKU_SO)) < 0) {
1643 debug("%s: could not register provider %s", __func__, 1679 debug("%s: could not register provider %s", __func__,
1644 provider_id); 1680 provider_id);
1645 goto out; 1681 goto out;
@@ -1710,7 +1746,7 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
1710 1746
1711 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { 1747 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
1712 debug("%s: using provider \"%s\"", __func__, provider_id); 1748 debug("%s: using provider \"%s\"", __func__, provider_id);
1713 } else if (pkcs11_register_provider(provider_id, pin, NULL, &p, 1749 } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p,
1714 CKU_SO) < 0) { 1750 CKU_SO) < 0) {
1715 debug("%s: could not register provider %s", __func__, 1751 debug("%s: could not register provider %s", __func__,
1716 provider_id); 1752 provider_id);