void show_pkcs11_ids( const char *const provider, bool cert_private ) { struct gc_arena gc = gc_new(); pkcs11h_certificate_id_list_t user_certificates = NULL; pkcs11h_certificate_id_list_t current = NULL; CK_RV rv = CKR_FUNCTION_FAILED; if ((rv = pkcs11h_initialize()) != CKR_OK) { msg(M_FATAL, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } if ((rv = pkcs11h_setLogHook(_pkcs11_openvpn_log, NULL)) != CKR_OK) { msg(M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } pkcs11h_setLogLevel(_pkcs11_msg_openvpn2pkcs11(get_debug_level())); if ((rv = pkcs11h_setProtectedAuthentication(TRUE)) != CKR_OK) { msg(M_FATAL, "PKCS#11: Cannot set protected authentication %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } if ((rv = pkcs11h_setPINPromptHook(_pkcs11_openvpn_show_pkcs11_ids_pin_prompt, NULL)) != CKR_OK) { msg(M_FATAL, "PKCS#11: Cannot set PIN hook %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } if ( (rv = pkcs11h_addProvider( provider, provider, TRUE, 0, FALSE, 0, cert_private ? TRUE : FALSE )) != CKR_OK ) { msg(M_FATAL, "PKCS#11: Cannot add provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage(rv)); goto cleanup; } if ( (rv = pkcs11h_certificate_enumCertificateIds( PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL, &user_certificates )) != CKR_OK ) { msg(M_FATAL, "PKCS#11: Cannot enumerate certificates %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } msg( M_INFO|M_NOPREFIX|M_NOLF, ( "\n" "The following objects are available for use.\n" "Each object shown below may be used as parameter to\n" "--pkcs11-id option please remember to use single quote mark.\n" ) ); for (current = user_certificates; current != NULL; current = current->next) { pkcs11h_certificate_t certificate = NULL; char *dn = NULL; char serial[1024] = {0}; char *ser = NULL; size_t ser_len = 0; if ( (rv = pkcs11h_certificate_serializeCertificateId( NULL, &ser_len, current->certificate_id )) != CKR_OK ) { msg(M_FATAL, "PKCS#11: Cannot serialize certificate %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup1; } if ( rv == CKR_OK && (ser = (char *)malloc(ser_len)) == NULL ) { msg(M_FATAL, "PKCS#11: Cannot allocate memory"); goto cleanup1; } if ( (rv = pkcs11h_certificate_serializeCertificateId( ser, &ser_len, current->certificate_id )) != CKR_OK ) { msg(M_FATAL, "PKCS#11: Cannot serialize certificate %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup1; } if ( (rv = pkcs11h_certificate_create( current->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &certificate )) ) { msg(M_FATAL, "PKCS#11: Cannot create certificate %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup1; } if ( (dn = pkcs11_certificate_dn( certificate, &gc )) == NULL ) { goto cleanup1; } if ( (pkcs11_certificate_serial( certificate, serial, sizeof(serial) )) ) { goto cleanup1; } msg( M_INFO|M_NOPREFIX|M_NOLF, ( "\n" "Certificate\n" " DN: %s\n" " Serial: %s\n" " Serialized id: %s\n" ), dn, serial, ser ); cleanup1: if (certificate != NULL) { pkcs11h_certificate_freeCertificate(certificate); certificate = NULL; } if (ser != NULL) { free(ser); ser = NULL; } } cleanup: if (user_certificates != NULL) { pkcs11h_certificate_freeCertificateIdList(user_certificates); user_certificates = NULL; } pkcs11h_terminate(); gc_free(&gc); }
bool pkcs11_management_id_get( const int index, char **id, char **base64 ) { pkcs11h_certificate_id_list_t id_list = NULL; pkcs11h_certificate_id_list_t entry = NULL; #if 0 /* certificate_id seems to be unused -- JY */ pkcs11h_certificate_id_t certificate_id = NULL; #endif pkcs11h_certificate_t certificate = NULL; CK_RV rv = CKR_OK; unsigned char *certificate_blob = NULL; size_t certificate_blob_size = 0; size_t max; char *internal_id = NULL; char *internal_base64 = NULL; int count = 0; bool success = false; ASSERT(id!=NULL); ASSERT(base64!=NULL); dmsg( D_PKCS11_DEBUG, "PKCS#11: pkcs11_management_id_get - entered index=%d", index ); *id = NULL; *base64 = NULL; if ( (rv = pkcs11h_certificate_enumCertificateIds( PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL, &id_list )) != CKR_OK ) { msg(M_WARN, "PKCS#11: Cannot get certificate list %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } entry = id_list; count = 0; while (entry != NULL && count != index) { count++; entry = entry->next; } if (entry == NULL) { dmsg( D_PKCS11_DEBUG, "PKCS#11: pkcs11_management_id_get - no certificate at index=%d", index ); goto cleanup; } if ( (rv = pkcs11h_certificate_serializeCertificateId( NULL, &max, entry->certificate_id )) != CKR_OK ) { msg(M_WARN, "PKCS#11: Cannot serialize certificate id %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } if ((internal_id = (char *)malloc(max)) == NULL) { msg(M_FATAL, "PKCS#11: Cannot allocate memory"); goto cleanup; } if ( (rv = pkcs11h_certificate_serializeCertificateId( internal_id, &max, entry->certificate_id )) != CKR_OK ) { msg(M_WARN, "PKCS#11: Cannot serialize certificate id %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } if ( (rv = pkcs11h_certificate_create( entry->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &certificate )) != CKR_OK ) { msg(M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } if ( (rv = pkcs11h_certificate_getCertificateBlob( certificate, NULL, &certificate_blob_size )) != CKR_OK ) { msg(M_WARN, "PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } if ((certificate_blob = (unsigned char *)malloc(certificate_blob_size)) == NULL) { msg(M_FATAL, "PKCS#11: Cannot allocate memory"); goto cleanup; } if ( (rv = pkcs11h_certificate_getCertificateBlob( certificate, certificate_blob, &certificate_blob_size )) != CKR_OK ) { msg(M_WARN, "PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } if (openvpn_base64_encode(certificate_blob, certificate_blob_size, &internal_base64) == -1) { msg(M_WARN, "PKCS#11: Cannot encode certificate"); goto cleanup; } *id = internal_id; internal_id = NULL; *base64 = internal_base64; internal_base64 = NULL; success = true; cleanup: if (id_list != NULL) { pkcs11h_certificate_freeCertificateIdList(id_list); id_list = NULL; } if (internal_id != NULL) { free(internal_id); internal_id = NULL; } if (internal_base64 != NULL) { free(internal_base64); internal_base64 = NULL; } if (certificate_blob != NULL) { free(certificate_blob); certificate_blob = NULL; } dmsg( D_PKCS11_DEBUG, "PKCS#11: pkcs11_management_id_get - return success=%d, id='%s'", success ? 1 : 0, *id ); return success; }
int tls_ctx_use_pkcs11( struct tls_root_ctx *const ssl_ctx, bool pkcs11_id_management, const char *const pkcs11_id ) { pkcs11h_certificate_id_t certificate_id = NULL; pkcs11h_certificate_t certificate = NULL; CK_RV rv = CKR_OK; bool ok = false; ASSERT(ssl_ctx!=NULL); ASSERT(pkcs11_id_management || pkcs11_id!=NULL); dmsg( D_PKCS11_DEBUG, "PKCS#11: tls_ctx_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_id_management=%d, pkcs11_id='%s'", (void *)ssl_ctx, pkcs11_id_management ? 1 : 0, pkcs11_id ); if (pkcs11_id_management) { struct user_pass id_resp; CLEAR(id_resp); id_resp.defined = false; id_resp.nocache = true; openvpn_snprintf( id_resp.username, sizeof(id_resp.username), "Please specify PKCS#11 id to use" ); if ( !get_user_pass( &id_resp, NULL, "pkcs11-id-request", GET_USER_PASS_MANAGEMENT|GET_USER_PASS_NEED_STR|GET_USER_PASS_NOFATAL ) ) { goto cleanup; } if ( (rv = pkcs11h_certificate_deserializeCertificateId( &certificate_id, id_resp.password )) != CKR_OK ) { msg(M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } } else { if ( (rv = pkcs11h_certificate_deserializeCertificateId( &certificate_id, pkcs11_id )) != CKR_OK ) { msg(M_WARN, "PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } } if ( (rv = pkcs11h_certificate_create( certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &certificate )) != CKR_OK ) { msg(M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; } if ( (pkcs11_init_tls_session( certificate, ssl_ctx )) ) { /* Handled by SSL context free */ certificate = NULL; goto cleanup; } /* Handled by SSL context free */ certificate = NULL; ok = true; cleanup: if (certificate != NULL) { pkcs11h_certificate_freeCertificate(certificate); certificate = NULL; } if (certificate_id != NULL) { pkcs11h_certificate_freeCertificateId(certificate_id); certificate_id = NULL; } dmsg( D_PKCS11_DEBUG, "PKCS#11: tls_ctx_use_pkcs11 - return ok=%d, rv=%ld", ok ? 1 : 0, rv ); return ok ? 1 : 0; }
/** Sign data (set by SETDATA) with certificate id in line. */ gpg_error_t cmd_pksign (assuan_context_t ctx, char *line) { static const unsigned char rmd160_prefix[] = /* (1.3.36.3.2.1) */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; static const unsigned char md5_prefix[] = /* (1.2.840.113549.2.5) */ { 0x30, 0x2c, 0x30, 0x09, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; static const unsigned char sha1_prefix[] = /* (1.3.14.3.2.26) */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; static const unsigned char sha224_prefix[] = /* (2.16.840.1.101.3.4.2.4) */ { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C }; static const unsigned char sha256_prefix[] = /* (2.16.840.1.101.3.4.2.1) */ { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; static const unsigned char sha384_prefix[] = /* (2.16.840.1.101.3.4.2.2) */ { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 }; static const unsigned char sha512_prefix[] = /* (2.16.840.1.101.3.4.2.3) */ { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 }; gpg_err_code_t error = GPG_ERR_GENERAL; pkcs11h_certificate_id_t cert_id = NULL; pkcs11h_certificate_t cert = NULL; cmd_data_t *data = (cmd_data_t *)assuan_get_pointer (ctx); cmd_data_t *_data = data; int need_free__data = 0; int session_locked = 0; unsigned char *sig = NULL; size_t sig_len; char hash[100] = ""; enum { INJECT_NONE, INJECT_RMD160, INJECT_MD5, INJECT_SHA1, INJECT_SHA224, INJECT_SHA256, INJECT_SHA384, INJECT_SHA512 } inject = INJECT_NONE; if (data->data == NULL) { error = GPG_ERR_INV_DATA; goto cleanup; } while (*line != '\x0' && (isspace (*line) || *line == '-')) { if (*line == '-') { static const char *hashprm = "--hash="; char *p = line; while (*line != '\x0' && !isspace (*line)) { line++; } line++; if (!strncmp (p, hashprm, strlen (hashprm))) { p += strlen (hashprm); *(line-1) = '\0'; snprintf (hash, sizeof(hash), "%s", p); } } else { line++; } } if (*line == '\x0') { error = GPG_ERR_INV_DATA; goto cleanup; } /* * sender prefixed data with algorithm OID */ if (strcmp(hash, "")) { if (!strcmp(hash, "rmd160") && data->size == (0x14 + sizeof(rmd160_prefix)) && !memcmp (data->data, rmd160_prefix, sizeof (rmd160_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "rmd160") && data->size == 0x14) { inject = INJECT_RMD160; } else if (!strcmp(hash, "md5") && data->size == (0x10 + sizeof(md5_prefix)) && !memcmp (data->data, md5_prefix, sizeof (md5_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "md5") && data->size == 0x10) { inject = INJECT_MD5; } else if (!strcmp(hash, "sha1") && data->size == (0x14 + sizeof(sha1_prefix)) && !memcmp (data->data, sha1_prefix, sizeof (sha1_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha1") && data->size == 0x14) { inject = INJECT_SHA1; } else if (!strcmp(hash, "sha224") && data->size == (0x1c + sizeof(sha224_prefix)) && !memcmp (data->data, sha224_prefix, sizeof (sha224_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha224") && data->size == 0x1c) { inject = INJECT_SHA224; } else if (!strcmp(hash, "sha256") && data->size == (0x20 + sizeof(sha256_prefix)) && !memcmp (data->data, sha256_prefix, sizeof (sha256_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha256") && data->size == 0x20) { inject = INJECT_SHA256; } else if (!strcmp(hash, "sha384") && data->size == (0x30 + sizeof(sha384_prefix)) && !memcmp (data->data, sha384_prefix, sizeof (sha384_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha384") && data->size == 0x30) { inject = INJECT_SHA384; } else if (!strcmp(hash, "sha512") && data->size == (0x40 + sizeof(sha512_prefix)) && !memcmp (data->data, sha512_prefix, sizeof (sha512_prefix))) { inject = INJECT_NONE; } else if (!strcmp(hash, "sha512") && data->size == 0x40) { inject = INJECT_SHA512; } else { common_log (LOG_DEBUG, "unsupported hash algo (hash=%s,size=%d)", hash, data->size); error = GPG_ERR_UNSUPPORTED_ALGORITHM; goto cleanup; } } else { if ( data->size == 0x10 + sizeof (md5_prefix) || data->size == 0x14 + sizeof (sha1_prefix) || data->size == 0x14 + sizeof (rmd160_prefix) ) { if ( memcmp (data->data, md5_prefix, sizeof (md5_prefix)) && memcmp (data->data, sha1_prefix, sizeof (sha1_prefix)) && memcmp (data->data, rmd160_prefix, sizeof (rmd160_prefix)) ) { error = GPG_ERR_UNSUPPORTED_ALGORITHM; goto cleanup; } } else { /* * unknown hash algorithm; * gnupg's scdaemon forces to SHA1 */ inject = INJECT_SHA1; } } if (inject != INJECT_NONE) { const unsigned char *oid; size_t oid_size; switch (inject) { case INJECT_RMD160: oid = rmd160_prefix; oid_size = sizeof (rmd160_prefix); break; case INJECT_MD5: oid = md5_prefix; oid_size = sizeof (md5_prefix); break; case INJECT_SHA1: oid = sha1_prefix; oid_size = sizeof (sha1_prefix); break; case INJECT_SHA224: oid = sha224_prefix; oid_size = sizeof (sha224_prefix); break; case INJECT_SHA256: oid = sha256_prefix; oid_size = sizeof(sha256_prefix); break; case INJECT_SHA384: oid = sha384_prefix; oid_size = sizeof(sha384_prefix); break; case INJECT_SHA512: oid = sha512_prefix; oid_size = sizeof(sha512_prefix); break; default: error = GPG_ERR_INV_DATA; goto cleanup; } need_free__data = 1; if ((_data = (cmd_data_t *)malloc (sizeof (cmd_data_t))) == NULL) { error = GPG_ERR_ENOMEM; goto cleanup; } if ((_data->data = (unsigned char *)malloc (data->size + oid_size)) == NULL) { error = GPG_ERR_ENOMEM; goto cleanup; } _data->size = 0; memmove (_data->data+_data->size, oid, oid_size); _data->size += oid_size; memmove (_data->data+_data->size, data->data, data->size); _data->size += data->size; } if ( (error = _get_certificate_by_name ( ctx, line, OPENPGP_SIGN, &cert_id, NULL )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_create ( cert_id, ctx, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &cert ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_lockSession (cert) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } session_locked = 1; if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_signAny ( cert, CKM_RSA_PKCS, _data->data, _data->size, NULL, &sig_len ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ((sig = (unsigned char *)malloc (sig_len)) == NULL) { error = GPG_ERR_ENOMEM; goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_signAny ( cert, CKM_RSA_PKCS, _data->data, _data->size, sig, &sig_len ) )) != GPG_ERR_NO_ERROR || (error = assuan_send_data(ctx, sig, sig_len)) != GPG_ERR_NO_ERROR ) { goto cleanup; } error = GPG_ERR_NO_ERROR; cleanup: if (session_locked) { pkcs11h_certificate_releaseSession (cert); session_locked = 0; } if (cert != NULL) { pkcs11h_certificate_freeCertificate (cert); cert = NULL; } if (cert_id != NULL) { pkcs11h_certificate_freeCertificateId (cert_id); cert_id = NULL; } if (sig != NULL) { free (sig); sig = NULL; } if (need_free__data) { free (_data->data); _data->data = NULL; free (_data); _data = NULL; } return gpg_error (error); }
static gpg_err_code_t get_cert_blob ( assuan_context_t ctx, pkcs11h_certificate_id_t cert_id, unsigned char **p_blob, size_t *p_blob_size ) { gpg_err_code_t error = GPG_ERR_GENERAL; pkcs11h_certificate_t cert = NULL; unsigned char *blob = NULL; size_t blob_size; *p_blob = NULL; *p_blob_size = 0; if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_create ( cert_id, ctx, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &cert ) )) != GPG_ERR_NO_ERROR || (error = common_map_pkcs11_error ( pkcs11h_certificate_getCertificateBlob ( cert, NULL, &blob_size ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ((blob = (unsigned char *)malloc (blob_size)) == NULL) { error = GPG_ERR_ENOMEM; goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_getCertificateBlob ( cert, blob, &blob_size ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } *p_blob = blob; *p_blob_size = blob_size; blob = NULL; error = GPG_ERR_NO_ERROR; cleanup: if (cert != NULL) { pkcs11h_certificate_freeCertificate (cert); cert = NULL; } if (blob != NULL) { free (blob); blob = NULL; } return error; }
/** Decrypt data (set by SETDATA) with certificate id in line. */ gpg_error_t cmd_pkdecrypt (assuan_context_t ctx, char *line) { gpg_err_code_t error = GPG_ERR_GENERAL; pkcs11h_certificate_id_t cert_id = NULL; pkcs11h_certificate_t cert = NULL; unsigned char *ptext = NULL; size_t ptext_len; int session_locked = 0; cmd_data_t *data = (cmd_data_t *)assuan_get_pointer (ctx); cmd_data_t _data; if ( data == NULL || data->data == NULL ) { error = GPG_ERR_INV_DATA; goto cleanup; } /* * Guess.. taken from openpgp card implementation * and java PKCS#11 provider. */ _data.data = data->data; _data.size = data->size; if ( *_data.data == 0 && ( _data.size == 129 || _data.size == 193 || _data.size == 257 || _data.size == 385 || _data.size == 513 ) ) { _data.data++; _data.size--; } if ( (error = _get_certificate_by_name ( ctx, line, OPENPGP_ENCR, &cert_id, NULL )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_create ( cert_id, ctx, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &cert ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_lockSession (cert) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } session_locked = 1; if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_decryptAny ( cert, CKM_RSA_PKCS, _data.data, _data.size, NULL, &ptext_len ) )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ((ptext = (unsigned char *)malloc (ptext_len)) == NULL) { error = GPG_ERR_ENOMEM; goto cleanup; } if ( (error = common_map_pkcs11_error ( pkcs11h_certificate_decryptAny ( cert, CKM_RSA_PKCS, _data.data, _data.size, ptext, &ptext_len ) )) != GPG_ERR_NO_ERROR || (error = assuan_write_status(ctx, "PADDING", "0")) != GPG_ERR_NO_ERROR || (error = assuan_send_data(ctx, ptext, ptext_len)) != GPG_ERR_NO_ERROR ) { goto cleanup; } error = GPG_ERR_NO_ERROR; cleanup: if (session_locked) { pkcs11h_certificate_releaseSession (cert); session_locked = 0; } if (cert != NULL) { pkcs11h_certificate_freeCertificate (cert); cert = NULL; } if (cert_id != NULL) { pkcs11h_certificate_freeCertificateId (cert_id); cert_id = NULL; } if (ptext != NULL) { free (ptext); ptext = NULL; } return gpg_error (error); }
int main () { pkcs11h_certificate_id_list_t issuers, certs, temp; pkcs11h_certificate_t cert; CK_RV rv; printf ("Initializing pkcs11-helper\n"); if ((rv = pkcs11h_initialize ()) != CKR_OK) { fatal ("pkcs11h_initialize failed", rv); } printf ("Registering pkcs11-helper hooks\n"); if ((rv = pkcs11h_setLogHook (_pkcs11h_hooks_log, NULL)) != CKR_OK) { fatal ("pkcs11h_setLogHook failed", rv); } pkcs11h_setLogLevel (TEST_LOG_LEVEL); if ((rv = pkcs11h_setTokenPromptHook (_pkcs11h_hooks_token_prompt, NULL)) != CKR_OK) { fatal ("pkcs11h_setTokenPromptHook failed", rv); } if ((rv = pkcs11h_setPINPromptHook (_pkcs11h_hooks_pin_prompt, NULL)) != CKR_OK) { fatal ("pkcs11h_setPINPromptHook failed", rv); } printf ("Adding provider '%s'\n", TEST_PROVIDER); if ( (rv = pkcs11h_addProvider ( TEST_PROVIDER, TEST_PROVIDER, FALSE, PKCS11H_PRIVATEMODE_MASK_AUTO, PKCS11H_SLOTEVENT_METHOD_AUTO, 0, FALSE )) != CKR_OK ) { fatal ("pkcs11h_addProvider failed", rv); } mypause ("Please remove all tokens, press <Enter>: "); printf ("Enumerating token certificate (list should be empty, no prompt)\n"); if ( (rv = pkcs11h_certificate_enumCertificateIds ( PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, &issuers, &certs )) != CKR_OK ) { fatal ("pkcs11h_certificate_enumCertificateIds failed", rv); } if (issuers != NULL || certs != NULL) { fatal ("No certificates should be found", rv); } mypause ("Please insert token, press <Enter>: "); printf ("Getting certificate cache, should be available certificates\n"); if ( (rv = pkcs11h_certificate_enumCertificateIds ( PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, &issuers, &certs )) != CKR_OK ) { fatal ("pkcs11h_certificate_enumCertificateIds failed", rv); } for (temp = issuers;temp != NULL;temp = temp->next) { printf ("Issuer: %s\n", temp->certificate_id->displayName); } for (temp = certs;temp != NULL;temp = temp->next) { printf ("Certificate: %s\n", temp->certificate_id->displayName); } if (certs == NULL) { fatal ("No certificates found", rv); } pkcs11h_certificate_freeCertificateIdList (issuers); pkcs11h_certificate_freeCertificateIdList (certs); mypause ("Please remove token, press <Enter>: "); printf ("Getting certificate cache, should be similar to last\n"); if ( (rv = pkcs11h_certificate_enumCertificateIds ( PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, &issuers, &certs )) != CKR_OK ) { fatal ("pkcs11h_certificate_enumCertificateIds failed", rv); } for (temp = issuers;temp != NULL;temp = temp->next) { printf ("Issuer: %s\n", temp->certificate_id->displayName); } for (temp = certs;temp != NULL;temp = temp->next) { printf ("Certificate: %s\n", temp->certificate_id->displayName); } if (certs == NULL) { fatal ("No certificates found", rv); } printf ("Creating certificate context\n"); if ( (rv = pkcs11h_certificate_create ( certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &cert )) != CKR_OK ) { fatal ("pkcs11h_certificate_create failed", rv); } printf ("Perforing signature #1 (you should be prompt for token and PIN)\n"); sign_test (cert); printf ("Perforing signature #2 (you should NOT be prompt for anything)\n"); sign_test (cert); mypause ("Please remove and insert token, press <Enter>: "); printf ("Perforing signature #3 (you should be prompt only for PIN)\n"); sign_test (cert); printf ("Perforing signature #4 (you should NOT be prompt for anything)\n"); if ((rv = pkcs11h_certificate_freeCertificate (cert)) != CKR_OK) { fatal ("pkcs11h_certificate_free failed", rv); } if ( (rv = pkcs11h_certificate_create ( certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &cert )) != CKR_OK ) { fatal ("pkcs11h_certificate_create failed", rv); } sign_test (cert); printf ("Terminating pkcs11-helper\n"); if ((rv = pkcs11h_certificate_freeCertificate (cert)) != CKR_OK) { fatal ("pkcs11h_certificate_free failed", rv); } pkcs11h_certificate_freeCertificateIdList (issuers); pkcs11h_certificate_freeCertificateIdList (certs); if ((rv = pkcs11h_terminate ()) != CKR_OK) { fatal ("pkcs11h_terminate failed", rv); } exit (0); return 0; }
int SSL_CTX_use_pkcs11 ( IN OUT SSL_CTX * const ssl_ctx, IN const char * const pkcs11_slot_type, IN const char * const pkcs11_slot, IN const char * const pkcs11_id_type, IN const char * const pkcs11_id ) { X509 *x509 = NULL; RSA *rsa = NULL; pkcs11h_certificate_id_t certificate_id = NULL; pkcs11h_certificate_t certificate = NULL; pkcs11h_openssl_session_t openssl_session = NULL; CK_RV rv = CKR_OK; bool fOK = true; ASSERT (ssl_ctx!=NULL); ASSERT (pkcs11_slot_type!=NULL); ASSERT (pkcs11_slot!=NULL); ASSERT (pkcs11_id_type!=NULL); ASSERT (pkcs11_id!=NULL); dmsg ( D_PKCS11_DEBUG, "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_slot_type='%s', pkcs11_slot='%s', pkcs11_id_type='%s', pkcs11_id='%s'", (void *)ssl_ctx, pkcs11_slot_type, pkcs11_slot, pkcs11_id_type, pkcs11_id ); ASSERT (ssl_ctx!=NULL); ASSERT (pkcs11_slot_type!=NULL); ASSERT (pkcs11_slot!=NULL); ASSERT (pkcs11_id_type!=NULL); ASSERT (pkcs11_id!=NULL); if ( fOK && (rv = pkcs11h_locate_certificate ( pkcs11_slot_type, pkcs11_slot, pkcs11_id_type, pkcs11_id, &certificate_id )) != CKR_OK ) { fOK = false; msg (M_WARN, "PKCS#11: Cannot set parameters %ld-'%s'", rv, pkcs11h_getMessage (rv)); } if ( fOK && (rv = pkcs11h_certificate_create ( certificate_id, PKCS11H_PIN_CACHE_INFINITE, &certificate )) != CKR_OK ) { fOK = false; msg (M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage (rv)); } if ( fOK && (openssl_session = pkcs11h_openssl_createSession (certificate)) == NULL ) { fOK = false; msg (M_WARN, "PKCS#11: Cannot initialize openssl session"); } if (fOK) { /* * Will be released by openssl_session */ certificate = NULL; } if ( fOK && (rsa = pkcs11h_openssl_getRSA (openssl_session)) == NULL ) { fOK = false; msg (M_WARN, "PKCS#11: Unable get rsa object"); } if ( fOK && (x509 = pkcs11h_openssl_getX509 (openssl_session)) == NULL ) { fOK = false; msg (M_WARN, "PKCS#11: Unable get certificate object"); } if ( fOK && !SSL_CTX_use_RSAPrivateKey (ssl_ctx, rsa) ) { fOK = false; msg (M_WARN, "PKCS#11: Cannot set private key for openssl"); } if ( fOK && !SSL_CTX_use_certificate (ssl_ctx, x509) ) { fOK = false; msg (M_WARN, "PKCS#11: Cannot set certificate for openssl"); } /* * openssl objects have reference * count, so release them */ if (x509 != NULL) { X509_free (x509); x509 = NULL; } if (rsa != NULL) { RSA_free (rsa); rsa = NULL; } if (certificate != NULL) { pkcs11h_freeCertificate (certificate); certificate = NULL; } if (certificate_id != NULL) { pkcs11h_freeCertificateId (certificate_id); certificate_id = NULL; } if (openssl_session != NULL) { pkcs11h_openssl_freeSession (openssl_session); openssl_session = NULL; } dmsg ( D_PKCS11_DEBUG, "PKCS#11: SSL_CTX_use_pkcs11 - return fOK=%d, rv=%ld", fOK ? 1 : 0, rv ); return fOK ? 1 : 0; }