|
33 | 33 |
|
34 | 34 | #include <openssl/err.h> |
35 | 35 | #ifndef OPENSSL_NO_ENGINE |
| 36 | +#if OPENSSL_VERSION_NUMBER < 0x30000000L |
36 | 37 | #include <openssl/engine.h> |
| 38 | +#else // OPENSSL_VERSION_NUMBER >= 0x30000000L |
| 39 | +#include <openssl/store.h> |
| 40 | +#endif |
37 | 41 | #endif |
38 | 42 | #include <openssl/ui.h> |
39 | 43 | #include <openssl/x509v3.h> |
@@ -1089,6 +1093,7 @@ int ssl_connect(struct tunnel *tunnel) |
1089 | 1093 | #endif |
1090 | 1094 |
|
1091 | 1095 | #ifndef OPENSSL_NO_ENGINE |
| 1096 | +#if OPENSSL_VERSION_NUMBER < 0x30000000L |
1092 | 1097 | /* Use PKCS11 engine for PIV if user-cert config starts with pkcs11 URI: */ |
1093 | 1098 | if (tunnel->config->use_engine > 0) { |
1094 | 1099 | ENGINE *e; |
@@ -1149,7 +1154,101 @@ int ssl_connect(struct tunnel *tunnel) |
1149 | 1154 | goto err_ssl_context; |
1150 | 1155 | } |
1151 | 1156 | } else { /* end PKCS11 engine */ |
1152 | | -#endif |
| 1157 | +#else // OPENSSL_VERSION_NUMBER >= 0x30000000L |
| 1158 | + /* OpenSSL 3.0+ provider-based PKCS#11 support */ |
| 1159 | + if (tunnel->config->use_engine > 0) { |
| 1160 | + // Debug: Print the certificate path/URI being used |
| 1161 | + log_debug_details("Attempting to load certificate from: %s\n", |
| 1162 | + tunnel->config->user_cert); |
| 1163 | + |
| 1164 | + // Use OSSL_STORE to load certificate and private key from PKCS#11 |
| 1165 | + OSSL_STORE_CTX *store_ctx = OSSL_STORE_open(tunnel->config->user_cert, |
| 1166 | + NULL, NULL, NULL, NULL); |
| 1167 | + |
| 1168 | + if (!store_ctx) { |
| 1169 | + log_error("PKCS11 OSSL_STORE_open failed: %s\n", |
| 1170 | + ERR_error_string(ERR_peek_last_error(), NULL)); |
| 1171 | + goto err_ssl_context; |
| 1172 | + } |
| 1173 | + |
| 1174 | + X509 *cert = NULL; |
| 1175 | + EVP_PKEY *pkey = NULL; |
| 1176 | + OSSL_STORE_INFO *info; |
| 1177 | + |
| 1178 | + // Load all objects from the store |
| 1179 | + while ((info = OSSL_STORE_load(store_ctx)) != NULL) { |
| 1180 | + int type = OSSL_STORE_INFO_get_type(info); |
| 1181 | + |
| 1182 | + if (type == OSSL_STORE_INFO_CERT) { |
| 1183 | + if (!cert) { |
| 1184 | + cert = OSSL_STORE_INFO_get1_CERT(info); |
| 1185 | + log_debug_details("Loaded certificate from PKCS#11 store\n"); |
| 1186 | + } else { |
| 1187 | + // Second certificate - indicates multiple certs |
| 1188 | + log_error("PKCS11: Multiple certificates found in store. Please specify more specific URL parameters (e.g., ?id=... or ?label=...) to select the desired certificate.\n"); |
| 1189 | + OSSL_STORE_INFO_free(info); |
| 1190 | + goto err_ssl_context; |
| 1191 | + } |
| 1192 | + } else if (type == OSSL_STORE_INFO_PKEY) { |
| 1193 | + if (!pkey) { |
| 1194 | + pkey = OSSL_STORE_INFO_get1_PKEY(info); |
| 1195 | + log_debug_details("Loaded private key from PKCS#11 store\n"); |
| 1196 | + } else { |
| 1197 | + // Second private key - indicates multiple keys |
| 1198 | + log_error("PKCS11: Multiple private keys found in store. Please specify more specific URL parameters (e.g., ?id=... or ?label=...) to select the desired private key.\n"); |
| 1199 | + OSSL_STORE_INFO_free(info); |
| 1200 | + goto err_ssl_context; |
| 1201 | + } |
| 1202 | + } |
| 1203 | + |
| 1204 | + OSSL_STORE_INFO_free(info); |
| 1205 | + } |
| 1206 | + |
| 1207 | + OSSL_STORE_close(store_ctx); |
| 1208 | + |
| 1209 | + // Check if we successfully loaded both certificate and private key |
| 1210 | + if (!cert) { |
| 1211 | + log_error("PKCS11: Could not load certificate from store\n"); |
| 1212 | + EVP_PKEY_free(pkey); // Free pkey if it was loaded but cert failed |
| 1213 | + goto err_ssl_context; |
| 1214 | + } |
| 1215 | + if (!pkey) { |
| 1216 | + log_error("PKCS11: Could not load private key from store\n"); |
| 1217 | + X509_free(cert); // Free cert if it was loaded but pkey failed |
| 1218 | + goto err_ssl_context; |
| 1219 | + } |
| 1220 | + |
| 1221 | + // Use the loaded certificate and private key |
| 1222 | + if (!SSL_CTX_use_certificate(tunnel->ssl_context, cert)) { |
| 1223 | + log_error("PKCS11 SSL_CTX_use_certificate failed: %s\n", |
| 1224 | + ERR_error_string(ERR_peek_last_error(), NULL)); |
| 1225 | + X509_free(cert); |
| 1226 | + EVP_PKEY_free(pkey); |
| 1227 | + goto err_ssl_context; |
| 1228 | + } |
| 1229 | + |
| 1230 | + if (!SSL_CTX_use_PrivateKey(tunnel->ssl_context, pkey)) { |
| 1231 | + log_error("PKCS11 SSL_CTX_use_PrivateKey failed: %s\n", |
| 1232 | + ERR_error_string(ERR_peek_last_error(), NULL)); |
| 1233 | + X509_free(cert); |
| 1234 | + EVP_PKEY_free(pkey); |
| 1235 | + goto err_ssl_context; |
| 1236 | + } |
| 1237 | + |
| 1238 | + if (!SSL_CTX_check_private_key(tunnel->ssl_context)) { |
| 1239 | + log_error("PKCS11 SSL_CTX_check_private_key: %s\n", |
| 1240 | + ERR_error_string(ERR_peek_last_error(), NULL)); |
| 1241 | + X509_free(cert); |
| 1242 | + EVP_PKEY_free(pkey); |
| 1243 | + goto err_ssl_context; |
| 1244 | + } |
| 1245 | + |
| 1246 | + // Clean up |
| 1247 | + X509_free(cert); |
| 1248 | + EVP_PKEY_free(pkey); |
| 1249 | + } else { /* end PKCS11 engine */ |
| 1250 | +#endif // OPENSSL_VERSION_NUMBER >= 0x30000000L |
| 1251 | +#endif // OPENSSL_NO_ENGINE |
1153 | 1252 | if (tunnel->config->user_cert) { |
1154 | 1253 | if (!SSL_CTX_use_certificate_chain_file( |
1155 | 1254 | tunnel->ssl_context, tunnel->config->user_cert)) { |
|
0 commit comments