static int _parcPkcs12KeyStore_ParseFile(PARCPkcs12KeyStore *keystore, const char *filename, const char *password) { parcSecurity_AssertIsInitialized(); FILE *fp = fopen(filename, "rb"); assertNotNull(fp, "Error opening %s: %s", filename, strerror(errno)); if (fp == NULL) { return -1; } PKCS12 *p12Keystore = NULL; d2i_PKCS12_fp(fp, &p12Keystore); fclose(fp); int success = PKCS12_parse(p12Keystore, password, &keystore->private_key, &keystore->x509_cert, NULL); PKCS12_free(p12Keystore); if (!success) { unsigned long errcode; while ((errcode = ERR_get_error()) != 0) { fprintf(stderr, "openssl error: %s\n", ERR_error_string(errcode, NULL)); } return -1; } keystore->public_key = X509_get_pubkey(keystore->x509_cert); return 0; }
int useCertFile(SSL_CTX* ctx, const char* path, const char* passphrase, const char* cacertfile) { FILE *p12_file; PKCS12 *p12_cert = NULL; EVP_PKEY *pkey; X509 *x509_cert; p12_file = fopen(path, "r"); if (!p12_file) { timestamp_f(stderr); perror(path); return -1; } d2i_PKCS12_fp(p12_file, &p12_cert); fclose(p12_file); if (!PKCS12_parse(p12_cert, passphrase, &pkey, &x509_cert, NULL)) { int error = ERR_get_error(); timestamp_f(stderr); fprintf(stderr, "failed to parse p12 file; error %d\n", error); PKCS12_free(p12_cert); return -1; } PKCS12_free(p12_cert); if (!SSL_CTX_use_certificate(ctx, x509_cert)) { int error = ERR_get_error(); timestamp_f(stderr); fprintf(stderr, "failed to set cert for SSL context; error %d\n", error); X509_free(x509_cert); EVP_PKEY_free(pkey); return -1; } X509_free(x509_cert); if (!SSL_CTX_use_PrivateKey(ctx, pkey)) { int error = ERR_get_error(); timestamp_f(stderr); fprintf(stderr, "failed to set private key for SSL context; error %d\n", error); EVP_PKEY_free(pkey); return -1; } EVP_PKEY_free(pkey); if (cacertfile && *cacertfile && !SSL_CTX_load_verify_locations(ctx, cacertfile, NULL)) { timestamp_f(stderr); fprintf(stderr, "failed to load root cert for verification from %s\n", cacertfile); return -1; } return 0; }
pki_pkcs12::pki_pkcs12(const QString fname, pem_password_cb *cb) :pki_base(fname) { FILE *fp; char pass[MAX_PASS_LENGTH]; EVP_PKEY *mykey = NULL; X509 *mycert = NULL; key=NULL; cert=NULL; passcb = cb; class_name="pki_pkcs12"; certstack = sk_X509_new_null(); pass_info p(XCA_TITLE, tr("Please enter the password to decrypt the PKCS#12 file.") + "\n'" + fname + "'"); fp = fopen(QString2filename(fname), "rb"); if (fp) { PKCS12 *pkcs12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (ign_openssl_error()) { if (pkcs12) PKCS12_free(pkcs12); throw errorEx(tr("Unable to load the PKCS#12 (pfx) file %1.").arg(fname)); } if (PKCS12_verify_mac(pkcs12, "", 0) || PKCS12_verify_mac(pkcs12, NULL, 0)) pass[0] = '\0'; else if (passcb(pass, MAX_PASS_LENGTH, 0, &p) < 0) { /* cancel pressed */ PKCS12_free(pkcs12); throw errorEx("",""); } PKCS12_parse(pkcs12, pass, &mykey, &mycert, &certstack); int error = ERR_peek_error(); if (ERR_GET_REASON(error) == PKCS12_R_MAC_VERIFY_FAILURE) { ign_openssl_error(); PKCS12_free(pkcs12); throw errorEx(getClassName(), tr("The supplied password was wrong (%1)").arg(ERR_reason_error_string(error))); } ign_openssl_error(); if (mycert) { if (mycert->aux && mycert->aux->alias) { alias = asn1ToQString(mycert->aux->alias); alias = QString::fromUtf8(alias.toAscii()); } cert = new pki_x509(mycert); if (alias.isEmpty()) { cert->autoIntName(); } else { cert->setIntName(alias); } alias = cert->getIntName(); } if (mykey) { key = new pki_evp(mykey); key->setIntName(alias + "_key"); key->bogusEncryptKey(); } PKCS12_free(pkcs12); } else fopen_error(fname); }
int sign_with_rsa_sha256(const char *input, const char *private_key, unsigned char *buffer_out, int *buffer_out_len) { FILE *fp; EVP_PKEY *pkey = 0; EVP_MD_CTX *ctx = 0; const EVP_MD *sha256_md = 0; unsigned int s = 0; PKCS12 *p12 = 0; X509 *cert = 0; OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); ctx = EVP_MD_CTX_create(); EVP_MD_CTX_init(ctx); sha256_md = EVP_sha256(); EVP_SignInit(ctx, sha256_md); EVP_SignUpdate(ctx, input, strlen(input)); ERR_load_crypto_strings(); if (!(fp = fopen(private_key, "rb"))) { perror("Error opening file with private key"); return -1; } p12 = d2i_PKCS12_fp(fp, NULL); fclose (fp); if (!p12) { perror("Error reading PKCS#12 file"); return -1; } if (!PKCS12_parse(p12, "notasecret", &pkey, &cert, NULL)) { perror("Error parsing PKCS#12 file"); return -1; } s = EVP_PKEY_size(pkey); EVP_SignFinal(ctx, buffer_out, &s, pkey); *buffer_out_len = s; PKCS12_free(p12); EVP_MD_CTX_destroy(ctx); X509_free(cert); EVP_cleanup(); return 0; }
int main(int argc, char **argv) { FILE *fp; EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; int i; if (argc != 4) { fprintf(stderr, "Usage: pkread p12file password opfile\n"); exit (1); } SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); if (!(fp = fopen(argv[1], "rb"))) { fprintf(stderr, "Error opening file %s\n", argv[1]); exit(1); } p12 = d2i_PKCS12_fp(fp, NULL); fclose (fp); if (!p12) { fprintf(stderr, "Error reading PKCS#12 file\n"); ERR_print_errors_fp(stderr); exit (1); } if (!PKCS12_parse(p12, argv[2], &pkey, &cert, &ca)) { fprintf(stderr, "Error parsing PKCS#12 file\n"); ERR_print_errors_fp(stderr); exit (1); } PKCS12_free(p12); if (!(fp = fopen(argv[3], "w"))) { fprintf(stderr, "Error opening file %s\n", argv[1]); exit(1); } if (pkey) { fprintf(fp, "***Private Key***\n"); PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL); } if (cert) { fprintf(fp, "***User Certificate***\n"); PEM_write_X509_AUX(fp, cert); } if (ca && sk_X509_num(ca)) { fprintf(fp, "***Other Certificates***\n"); for (i = 0; i < sk_X509_num(ca); i++) PEM_write_X509_AUX(fp, sk_X509_value(ca, i)); } fclose(fp); return 0; }
static int loadPkcs12( const char *fn, const char* pw) { /* you are lost in a maze of twisty crypto algorithms... */ PKCS12 *p12; X509 *x509; EVP_PKEY *pkey; FILE *fp; int ret; fp = fopen(fn, "r"); if (fp == NULL) { printf("Could not open file `%s\n", fn); return -1; } p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (p12 == NULL) { printf("Could not read certificate from file `%s\n",fn); return -1; } /* we need some more for the P12 decoding */ OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); ERR_load_crypto_strings(); ret = PKCS12_parse(p12, getenv(pw),&pkey, &x509, NULL); saveCertificateHome(x509, true); savePKeyHome( x509, pkey); PKCS12_free(p12); if (ret != 1) { printf("Error parsing certificate (incorrect password?): %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } return 0; }
int tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, const char *pkcs12_file_inline, bool load_ca_file ) { FILE *fp; EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; int i; char password[256]; ASSERT(NULL != ctx); if (!strcmp (pkcs12_file, INLINE_FILE_TAG) && pkcs12_file_inline) { BIO *b64 = BIO_new(BIO_f_base64()); BIO *bio = BIO_new_mem_buf((void *) pkcs12_file_inline, (int) strlen(pkcs12_file_inline)); ASSERT(b64 && bio); BIO_push(b64, bio); p12 = d2i_PKCS12_bio(b64, NULL); if (!p12) msg(M_SSLERR, "Error reading inline PKCS#12 file"); BIO_free(b64); BIO_free(bio); } else { /* Load the PKCS #12 file */ if (!(fp = platform_fopen(pkcs12_file, "rb"))) msg(M_SSLERR, "Error opening file %s", pkcs12_file); p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (!p12) msg(M_SSLERR, "Error reading PKCS#12 file %s", pkcs12_file); } /* Parse the PKCS #12 file */ if (!PKCS12_parse(p12, "", &pkey, &cert, &ca)) { pem_password_callback (password, sizeof(password) - 1, 0, NULL); /* Reparse the PKCS #12 file with password */ ca = NULL; if (!PKCS12_parse(p12, password, &pkey, &cert, &ca)) { #ifdef ENABLE_MANAGEMENT if (management && (ERR_GET_REASON (ERR_peek_error()) == PKCS12_R_MAC_VERIFY_FAILURE)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif PKCS12_free(p12); return 1; } } PKCS12_free(p12); /* Load Certificate */ if (!SSL_CTX_use_certificate (ctx->ctx, cert)) msg (M_SSLERR, "Cannot use certificate"); /* Load Private Key */ if (!SSL_CTX_use_PrivateKey (ctx->ctx, pkey)) msg (M_SSLERR, "Cannot use private key"); warn_if_group_others_accessible (pkcs12_file); /* Check Private Key */ if (!SSL_CTX_check_private_key (ctx->ctx)) msg (M_SSLERR, "Private key does not match the certificate"); /* Set Certificate Verification chain */ if (load_ca_file) { if (ca && sk_X509_num(ca)) { for (i = 0; i < sk_X509_num(ca); i++) { if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)"); if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)"); } } } return 0; }
/* ChangePasswordPKCS12() returns: * -1 Wrong password * 0 Changing password failed for unknown reason * 1 Password changed successfully */ int ChangePasswordPKCS12(HWND hwndDlg) { char keyfile[MAX_PATH]; char oldpsw[50]; char newpsw[50]; WCHAR oldpsw_unicode[50]; WCHAR newpsw_unicode[50]; FILE *fp; EVP_PKEY *privkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; PKCS12 *new_p12; char *alias; /* Get filename, old_psw and new_psw from Dialog */ GetDlgItemText(hwndDlg, TEXT_KEYFILE, keyfile, sizeof(keyfile) - 1); GetDlgItemTextW(hwndDlg, EDIT_PSW_CURRENT, oldpsw_unicode, sizeof(oldpsw_unicode)/2 - 1); GetDlgItemTextW(hwndDlg, EDIT_PSW_NEW, newpsw_unicode, sizeof(newpsw_unicode)/2 - 1); /* Convert Unicode to ASCII (CP850) */ ConvertUnicode2Ascii(oldpsw_unicode, oldpsw, sizeof(oldpsw)); if (!ConvertUnicode2Ascii(newpsw_unicode, newpsw, sizeof(newpsw))) { ShowLocalizedMsg(GUI_NAME, ERR_INVALID_CHARS_IN_PSW, ""); return(-1); } /* Load the PKCS #12 file */ if (!(fp = fopen(keyfile, "rb"))) { /* error opening file */ ShowLocalizedMsg(GUI_NAME, ERR_OPEN_PRIVATE_KEY_FILE, keyfile); return(0); } p12 = d2i_PKCS12_fp(fp, NULL); fclose (fp); if (!p12) { /* error reading PKCS #12 */ ShowLocalizedMsg(GUI_NAME, ERR_READ_PKCS12, keyfile); return(0); } /* Parse the PKCS #12 file */ if (!PKCS12_parse(p12, oldpsw, &privkey, &cert, &ca)) { /* old password incorrect */ ShowLocalizedMsg(GUI_NAME, ERR_OLD_PWD_INCORRECT, ""); PKCS12_free(p12); return(-1); } /* Free old PKCS12 object */ PKCS12_free(p12); /* Get FriendlyName of old cert */ alias = X509_alias_get0(cert, NULL); /* Create new PKCS12 object */ p12 = PKCS12_create(newpsw, alias, privkey, cert, ca, 0,0,0,0,0); if (!p12) { /* create failed */ //ShowMsg(GUI_NAME, ERR_error_string(ERR_peek_last_error(), NULL)); ShowLocalizedMsg(GUI_NAME, ERR_CREATE_PKCS12, ""); return(0); } /* Free old key, cert and ca */ EVP_PKEY_free(privkey); X509_free(cert); sk_X509_pop_free(ca, X509_free); /* Open keyfile for writing */ if (!(fp = fopen(keyfile, "wb"))) { ShowLocalizedMsg(GUI_NAME, ERR_OPEN_WRITE_KEY, keyfile); PKCS12_free(p12); return(0); } /* Write new key to file */ i2d_PKCS12_fp(fp, p12); PKCS12_free(p12); fclose(fp); /* signal success to user */ ShowLocalizedMsg(GUI_NAME, INFO_PWD_CHANGED, ""); return(1); }
static int cert_stuff(struct connectdata *conn, SSL_CTX* ctx, char *cert_file, const char *cert_type, char *key_file, const char *key_type) { struct SessionHandle *data = conn->data; int file_type; if(cert_file != NULL) { SSL *ssl; X509 *x509; int cert_done = 0; if(data->set.key_passwd) { #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* * If password has been given, we store that in the global * area (*shudder*) for a while: */ size_t len = strlen(data->set.key_passwd); if(len < sizeof(global_passwd)) memcpy(global_passwd, data->set.key_passwd, len+1); #else /* * We set the password in the callback userdata */ SSL_CTX_set_default_passwd_cb_userdata(ctx, data->set.key_passwd); #endif /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } file_type = do_file_type(cert_type); #define SSL_CLIENT_CERT_ERR \ "unable to use client certificate (no key found or wrong pass phrase?)" switch(file_type) { case SSL_FILETYPE_PEM: /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ if(SSL_CTX_use_certificate_chain_file(ctx, cert_file) != 1) { failf(data, SSL_CLIENT_CERT_ERR); return 0; } break; case SSL_FILETYPE_ASN1: /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but we use the case above for PEM so this can only be performed with ASN1 files. */ if(SSL_CTX_use_certificate_file(ctx, cert_file, file_type) != 1) { failf(data, SSL_CLIENT_CERT_ERR); return 0; } break; case SSL_FILETYPE_ENGINE: failf(data, "file type ENG for certificate not implemented"); return 0; case SSL_FILETYPE_PKCS12: { #ifdef HAVE_PKCS12_SUPPORT FILE *f; PKCS12 *p12; EVP_PKEY *pri; f = fopen(cert_file,"rb"); if (!f) { failf(data, "could not open PKCS12 file '%s'", cert_file); return 0; } p12 = d2i_PKCS12_fp(f, NULL); fclose(f); PKCS12_PBE_add(); if (!PKCS12_parse(p12, data->set.key_passwd, &pri, &x509, NULL)) { failf(data, "could not parse PKCS12 file, check password, OpenSSL error %s", ERR_error_string(ERR_get_error(), NULL) ); return 0; } PKCS12_free(p12); if(SSL_CTX_use_certificate(ctx, x509) != 1) { failf(data, SSL_CLIENT_CERT_ERR); EVP_PKEY_free(pri); X509_free(x509); return 0; } if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) { failf(data, "unable to use private key from PKCS12 file '%s'", cert_file); EVP_PKEY_free(pri); X509_free(x509); return 0; } EVP_PKEY_free(pri); X509_free(x509); cert_done = 1; break; #else failf(data, "file type P12 for certificate not supported"); return 0; #endif } default: failf(data, "not supported file type '%s' for certificate", cert_type); return 0; } file_type = do_file_type(key_type); switch(file_type) { case SSL_FILETYPE_PEM: if(cert_done) break; if(key_file == NULL) /* cert & key can only be in PEM case in the same file */ key_file=cert_file; case SSL_FILETYPE_ASN1: if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { failf(data, "unable to set private key file: '%s' type %s\n", key_file, key_type?key_type:"PEM"); return 0; } break; case SSL_FILETYPE_ENGINE: #ifdef HAVE_OPENSSL_ENGINE_H { /* XXXX still needs some work */ EVP_PKEY *priv_key = NULL; if(conn && conn->data && conn->data->state.engine) { #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS UI_METHOD *ui_method = UI_OpenSSL(); #endif if(!key_file || !key_file[0]) { failf(data, "no key set to load from crypto engine\n"); return 0; } /* the typecast below was added to please mingw32 */ priv_key = (EVP_PKEY *) ENGINE_load_private_key(conn->data->state.engine,key_file, #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS ui_method, #endif data->set.key_passwd); if(!priv_key) { failf(data, "failed to load private key from crypto engine\n"); return 0; } if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { failf(data, "unable to set private key\n"); EVP_PKEY_free(priv_key); return 0; } EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ } else { failf(data, "crypto engine not set, can't load private key\n"); return 0; } } break; #else failf(data, "file type ENG for private key not supported\n"); return 0; #endif case SSL_FILETYPE_PKCS12: if(!cert_done) { failf(data, "file type P12 for private key not supported\n"); return 0; } break; default: failf(data, "not supported file type for private key\n"); return 0; } ssl=SSL_new(ctx); if (NULL == ssl) { failf(data,"unable to create an SSL structure\n"); return 0; } x509=SSL_get_certificate(ssl); /* This version was provided by Evan Jordan and is supposed to not leak memory as the previous version: */ if(x509 != NULL) { EVP_PKEY *pktmp = X509_get_pubkey(x509); EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(ssl)); EVP_PKEY_free(pktmp); } SSL_free(ssl); /* If we are using DSA, we can copy the parameters from * the private key */ /* Now we know that a key and cert have been set against * the SSL context */ if(!SSL_CTX_check_private_key(ctx)) { failf(data, "Private key does not match the certificate public key"); return(0); } #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* erase it now */ memset(global_passwd, 0, sizeof(global_passwd)); #endif } return(1); }
apn_return apn_ssl_connect(apn_ctx_t *const ctx) { assert(ctx); SSL_CTX *ssl_ctx = NULL; if (NULL == (ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Could not initialize SSL context: %s", ERR_error_string(ERR_get_error(), NULL)); return APN_ERROR; } SSL_CTX_set_ex_data(ssl_ctx, 0, ctx); SSL_CTX_set_info_callback(ssl_ctx, __apn_ssl_info_callback); X509 *cert = NULL; if (ctx->pkcs12_file && ctx->pkcs12_pass) { FILE *pkcs12_file = NULL; #ifdef _WIN32 fopen_s(&pkcs12_file, ctx->pkcs12_file, "r"); #else pkcs12_file = fopen(ctx->pkcs12_file, "r"); #endif if (!pkcs12_file) { char *error = apn_error_string(errno); apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to open file %s: %s (errno: %d)", ctx->pkcs12_file, error, errno); free(error); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12; return APN_ERROR; } PKCS12 *pkcs12_cert = NULL; d2i_PKCS12_fp(pkcs12_file, &pkcs12_cert); fclose(pkcs12_file); EVP_PKEY *private_key = NULL; if (!PKCS12_parse(pkcs12_cert, ctx->pkcs12_pass, &private_key, &cert, NULL)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified PKCS#12 file: %s", ERR_error_string(ERR_get_error(), NULL)); PKCS12_free(pkcs12_cert); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12; return APN_ERROR; } PKCS12_free(pkcs12_cert); if (!SSL_CTX_use_certificate(ssl_ctx, cert)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified PKCS#12 file: %s", ERR_error_string(ERR_get_error(), NULL)); X509_free(cert); EVP_PKEY_free(private_key); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12; return APN_ERROR; } if (!SSL_CTX_use_PrivateKey(ssl_ctx, private_key)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified PKCS#12 file: %s", ERR_error_string(ERR_get_error(), NULL)); X509_free(cert); EVP_PKEY_free(private_key); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PKCS12; return APN_ERROR; } EVP_PKEY_free(private_key); } else { FILE *cert_file = NULL; #ifdef _WIN32 fopen_s(&cert_file, ctx->certificate_file, "r"); #else cert_file = fopen(ctx->certificate_file, "r"); #endif if (!cert_file) { char *error = apn_error_string(errno); apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to open file %s: %s (errno: %d)", ctx->pkcs12_file, error, errno); free(error); X509_free(cert); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE; return APN_ERROR; } cert = PEM_read_X509(cert_file, NULL, NULL, NULL); if (!cert) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified certificate: %s", ERR_error_string(ERR_get_error(), NULL)); SSL_CTX_free(ssl_ctx); fclose(cert_file); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE; return EXIT_FAILURE; } fclose(cert_file); if (!SSL_CTX_use_certificate(ssl_ctx, cert)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified certificate: %s", ERR_error_string(ERR_get_error(), NULL)); X509_free(cert); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE; return APN_ERROR; } SSL_CTX_set_default_passwd_cb(ssl_ctx, __apn_ssl_password_callback); char *password = NULL; if (ctx->private_key_pass) { password = apn_strndup(ctx->private_key_pass, strlen(ctx->private_key_pass)); if (!password) { X509_free(cert); SSL_CTX_free(ssl_ctx); return APN_ERROR; } SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, password); } else { SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, NULL); } if (!SSL_CTX_use_PrivateKey_file(ssl_ctx, ctx->private_key_file, SSL_FILETYPE_PEM)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified private key: %s", ERR_error_string(ERR_get_error(), NULL)); apn_strfree(&password); X509_free(cert); SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PRIVATE_KEY; return APN_ERROR; } apn_strfree(&password); if (!SSL_CTX_check_private_key(ssl_ctx)) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to use specified private key: %s", ERR_error_string(ERR_get_error(), NULL)); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_PRIVATE_KEY; X509_free(cert); SSL_CTX_free(ssl_ctx); return APN_ERROR; } } if(cert) { char *subject = __apn_cert_subject_string(cert); apn_log(ctx, APN_LOG_LEVEL_INFO, "Local certificate subject: %s", subject); char *issuer = __apn_cert_issuer_string(cert); apn_log(ctx, APN_LOG_LEVEL_INFO, "Local certificate issuer: %s", issuer); free(subject); free(issuer); char *cn = __apn_cert_subject_value_by_nib(cert, __APN_X509_ENTRY_CN); X509_free(cert); if(cn) { uint8_t invalid_cert = 0; if(apn_mode(ctx) == APN_MODE_PRODUCTION && 0 != strncmp("Apple Production", cn, 16)) { invalid_cert = 1; apn_log(ctx, APN_LOG_LEVEL_ERROR, "Invalid certificate. You are using a PRODUCTION mode, but certificate was created for usage in SANDBOX"); } else if (apn_mode(ctx) == APN_MODE_SANDBOX && 0 != strncmp("Apple Development", cn, 17)) { invalid_cert = 1; apn_log(ctx, APN_LOG_LEVEL_ERROR, "Invalid certificate. You are using a SANDBOX mode, but certificate was created for usage in PRODUCTION"); } free(cn); if(1 == invalid_cert) { SSL_CTX_free(ssl_ctx); errno = APN_ERR_UNABLE_TO_USE_SPECIFIED_CERTIFICATE; return APN_ERROR; } } } ctx->ssl = SSL_new(ssl_ctx); SSL_CTX_free(ssl_ctx); if (!ctx->ssl) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Could not initialize SSL"); errno = APN_ERR_UNABLE_TO_ESTABLISH_SSL_CONNECTION; return APN_ERROR; } int ret = 0; if (-1 == (ret = SSL_set_fd(ctx->ssl, ctx->sock))) { apn_log(ctx, APN_LOG_LEVEL_ERROR, "Unable to attach socket to SSL: SSL_set_fd() failed (%d)", SSL_get_error(ctx->ssl, ret)); errno = APN_ERR_UNABLE_TO_ESTABLISH_SSL_CONNECTION; return APN_ERROR; } if (1 > (ret = SSL_connect(ctx->ssl))) { char *error = apn_error_string(errno); apn_log(ctx, APN_LOG_LEVEL_ERROR, "Could not initialize SSL connection: SSL_connect() failed: %s, %s (errno: %d):", ERR_error_string((unsigned long) SSL_get_error(ctx->ssl, ret), NULL), error, errno); free(error); return APN_ERROR; } apn_log(ctx, APN_LOG_LEVEL_INFO, "SSL connection has been established"); X509 *remote_cert = SSL_get_peer_certificate(ctx->ssl); if (remote_cert) { char *subject = __apn_cert_subject_string(remote_cert); apn_log(ctx, APN_LOG_LEVEL_INFO, "Remote certificate subject: %s", subject); char *issuer = __apn_cert_issuer_string(remote_cert); apn_log(ctx, APN_LOG_LEVEL_INFO, "Remote certificate issuer: %s", issuer); free(subject); free(issuer); X509_free(remote_cert); } return APN_SUCCESS; }
static int sign_with_p12_key(const struct http_io_conf *const config, char *key_file, const char *pwd, char *plain_text, char *signed_buf, size_t buflen) { unsigned char hash[SHA256_DIGEST_LENGTH]; unsigned char sign[256]; unsigned int sign_len = 0; FILE *fp = NULL; PKCS12 *p12 = NULL; EVP_PKEY *pkey = NULL; X509 *x509 = NULL; EVP_MD_CTX *ctx = NULL; RSA *prikey = NULL; SHA256_CTX sha256; const char *c; int ret; memset(hash, 0, SHA256_DIGEST_LENGTH); memset(sign, 0, 256); if (!(fp = fopen(key_file, "rb"))){ (*config->log)(LOG_ERR, "Error opening cert file %s: %s", key_file, strerror(errno)); return 1; } p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (!p12) { (*config->log)(LOG_ERR, "Error reading PKCS#12 file: %s", strerror(errno)); return 1; } STACK_OF(X509) *ca = NULL; ret = PKCS12_parse(p12, pwd, &pkey, &x509, &ca); PKCS12_free(p12); if (ret == 0) { (*config->log)(LOG_ERR, "Error parsing PKCS#12 file: %s", strerror(errno)); return 1; } sign_len = EVP_PKEY_size(pkey); ctx = EVP_MD_CTX_create(); EVP_MD_CTX_init(ctx); prikey = EVP_PKEY_get1_RSA(pkey); SHA256_Init(&sha256); c = plain_text; SHA256_Update(&sha256, c, strlen(c)); SHA256_Final(hash, &sha256); ret = RSA_sign(NID_sha256, hash, SHA256_DIGEST_LENGTH, sign, &sign_len, prikey); EVP_MD_CTX_destroy(ctx); RSA_free(prikey); EVP_PKEY_free(pkey); X509_free(x509); if (ret == 0) { (*config->log)(LOG_ERR, "Signing p12 key with RSA Signature failed "); return 1; } memset(signed_buf, 0, buflen); http_io_base64_encode_safe(signed_buf, buflen, sign, sign_len); return 0; }
char * PKCS7_GetSign(char*certFile,char* pwd, char* plainText,int flag) { //取PKCS12對象 FILE* fp; if (!(fp = fopen(certFile, "rb"))) { fprintf(stderr, "Error opening file %s\n", certFile); return NULL; } PKCS12 *p12= d2i_PKCS12_fp(fp, NULL); fclose (fp); if (!p12) { fprintf(stderr, "Error reading PKCS#12 file\n"); ERR_print_errors_fp(stderr); return NULL; } //取pkey對象、X509證書、證書鏈 EVP_PKEY *pkey=NULL; X509 *x509=NULL; STACK_OF(X509) *ca = NULL; if (!PKCS12_parse(p12, pwd, &pkey, &x509, &ca)) { fprintf(stderr, "Error parsing PKCS#12 file\n"); ERR_print_errors_fp(stderr); return NULL; } PKCS12_free(p12); //明文轉為BIO對象 //《vc++网络安全编程范例(14)-openssl bio编程 》 http://www.2cto.com/kf/201112/115018.html BIO *bio = BIO_new(BIO_s_mem()); BIO_puts(bio,plainText); //數字簽名 //PKCS7_NOCHAIN:签名中不包含证书链,第三个参数为NULL值的话,可不加这个FLAG标记 //PKCS7_NOSMIMECAP:签名不需要支持SMIME PKCS7* pkcs7 = PKCS7_sign(x509,pkey, ca,bio, flag); if(pkcs7==NULL) { ERR_print_errors_fp(stderr); return NULL; } //共有两种编码,一种是ASN1,另一种是DER编码。 //取數據簽名(DER格式) //openssl学习笔记之pkcs7-data内容类型的编码解码 //http://ipedo.i.sohu.com/blog/view/114822358.htm //入口:pkcs7对象 //出口:der对象 unsigned char *der; unsigned char *derTmp; unsigned long derlen; derlen = i2d_PKCS7(pkcs7,NULL); der = (unsigned char *) malloc(derlen); memset(der,0,derlen); derTmp = der; i2d_PKCS7(pkcs7,&derTmp); //DER转BASE64 return base64(der,derlen); }
/** * \fn resultP12ToPem p12ToPem (string, string) * \brief Convert P12 to PEM * \param string p12File Path to P12 file * \param string p12Passwd Password to open P12 file * \return result (bool ReturnCode, Int ErrorCode, String Comment, String PrivateKey, String Certificate) */ resultP12ToPem p12ToPem(string p12File, string p12Passwd) { FILE *fp; PKCS12 *p12 = NULL; EVP_PKEY *pkey = NULL; X509 *cert = NULL; STACK_OF(X509) *ca = NULL; BIO *o = BIO_new(BIO_s_mem()); string privateKey = ""; string certificate = ""; resultP12ToPem ret; ret.ReturnCode = false; ret.ErrorCode = 0; ret.Comment = ""; ret.PrivateKey = ""; ret.Certificate = ""; SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); if(!(fp = fopen(p12File.c_str(), "rb"))) { ret.ErrorCode = 1; ret.Comment = strerror(errno); return ret; } p12 = d2i_PKCS12_fp(fp, &p12); fclose (fp); if (!p12) { ret.ErrorCode = 2; ret.Comment = "Unable to open PKCS#12 file"; return ret; } if (!PKCS12_parse(p12, p12Passwd.c_str(), &pkey, &cert, &ca)) { ret.ErrorCode = 3; ret.Comment = "Unable to parse PKCS#12 file (wrong password ?)"; return ret; } PKCS12_free(p12); if (!(pkey && cert)) { ret.ErrorCode = 4; ret.Comment = "Certificate and/or key file doesn't exists"; } else { PEM_write_bio_PrivateKey(o, pkey, 0, 0, 0, NULL, 0); privateKey = x509ToString(o); PEM_write_bio_X509(o, cert); certificate = x509ToString(o); BIO_free(o); ret.ReturnCode = true; ret.ErrorCode = 0; ret.Comment = "All is fine"; ret.PrivateKey = privateKey; ret.Certificate = certificate; } return ret; }
static int tls_read_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, const char *private_key, const char *passwd) { #ifdef PKCS12_FUNCS FILE *f; PKCS12 *p12; EVP_PKEY *pkey; X509 *cert; int res = 0; f = fopen(private_key, "r"); if (f == NULL) return -1; p12 = d2i_PKCS12_fp(f, NULL); if (p12 == NULL) { wpa_printf(MSG_DEBUG, "TLS: Failed to read PKCS12 file '%s'", private_key); fclose(f); return -1; } fclose(f); pkey = NULL; cert = NULL; if (!PKCS12_parse(p12, passwd, &pkey, &cert, NULL)) { wpa_printf(MSG_DEBUG, "TLS: Failed to parse PKCS12 file '%s': " "%s", private_key, ERR_error_string(ERR_get_error(), NULL)); return -1; } wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 file '%s'", private_key); if (cert) { wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12"); if (ssl) { if (SSL_use_certificate(ssl, cert) != 1) res = -1; } else { if (SSL_CTX_use_certificate(ssl_ctx, cert) != 1) res = -1; } X509_free(cert); } if (pkey) { wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12"); if (ssl) { if (SSL_use_PrivateKey(ssl, pkey) != 1) res = -1; } else { if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) res = -1; } EVP_PKEY_free(pkey); } PKCS12_free(p12); return res; #else /* PKCS12_FUNCS */ wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read " "p12/pfx files"); return -1; #endif /* PKCS12_FUNCS */ }
int main(int argc, char **argv) { FILE *fp = NULL; EVP_PKEY *pkey = NULL; X509 *cert = NULL; STACK_OF(X509) *ca = NULL; PKCS12 *p12 = NULL; char *pass = strdup(""); int i; if (argc != 2) { fprintf(stderr, "[!] Usage: %s certificate.p12\n", argv[0]); exit(1); } printf("[+] Initializing OpenSSL\n"); SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); printf("[+] Opening PKCS#12 certificate\n"); if (!(fp = fopen(argv[1], "r"))) { fprintf(stderr, "[!] Unable to open certificate `%s'\n", argv[1]); goto endpkcs12; } if (chdir(dirname(argv[1])) == -1) { fprintf(stderr, "[!] Unable to change directory to `%s'\n", dirname(argv[1])); goto endpkcs12; } p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); fp = NULL; if (!p12) { fprintf(stderr, "[!] Unable to parse PKCS#12 certificate: %s\n", ERR_reason_error_string(ERR_get_error())); goto endpkcs12; } while (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { ca = NULL; free(pass); if (getpassword("[?] Password: "******"[!] PKCS#12 certificate is incomplete\n"); goto endpkcs12; } #define PEM_w(path, call) \ do { \ if (!(fp = fopen(path, "w"))) { \ fprintf(stderr, "[!] Unable to open `%s'\n", path); \ goto endpkcs12; \ } \ printf("[+] Write certificate to `%s'\n", path); \ call; \ fclose(fp); fp = NULL; \ } while(0) PEM_w("user.pem", PEM_write_X509(fp, cert)); PEM_w("user.key", PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL)); PEM_w("cacert.pem", for (i = 0; i < sk_X509_num(ca); i++) PEM_write_X509(fp, sk_X509_value(ca, i))); sk_free(ca); X509_free(cert); EVP_PKEY_free(pkey); exit(0); endpkcs12: if (pass) free(pass); if (ca) sk_free(ca); if (cert) X509_free(cert); if (pkey) EVP_PKEY_free(pkey); if (p12) PKCS12_free(p12); if (fp) fclose(fp); exit(1); }
static int load_certificate(struct openconnect_info *vpninfo) { if (!strncmp(vpninfo->sslkey, "pkcs11:", 7) || !strncmp(vpninfo->cert, "pkcs11:", 7)) { vpn_progress(vpninfo, PRG_ERR, _("This binary built without PKCS#11 support\n")); return -EINVAL; } vpn_progress(vpninfo, PRG_TRACE, _("Using certificate file %s\n"), vpninfo->cert); if (strncmp(vpninfo->cert, "keystore:", 9) && (vpninfo->cert_type == CERT_TYPE_PKCS12 || vpninfo->cert_type == CERT_TYPE_UNKNOWN)) { FILE *f; PKCS12 *p12; f = fopen(vpninfo->cert, "r"); if (!f) { vpn_progress(vpninfo, PRG_ERR, _("Failed to open certificate file %s: %s\n"), vpninfo->cert, strerror(errno)); return -ENOENT; } p12 = d2i_PKCS12_fp(f, NULL); fclose(f); if (p12) return load_pkcs12_certificate(vpninfo, p12); /* Not PKCS#12 */ if (vpninfo->cert_type == CERT_TYPE_PKCS12) { vpn_progress(vpninfo, PRG_ERR, _("Read PKCS#12 failed\n")); openconnect_report_ssl_errors(vpninfo); return -EINVAL; } /* Clear error and fall through to see if it's a PEM file... */ ERR_clear_error(); } /* It's PEM or TPM now, and either way we need to load the plain cert: */ #ifdef ANDROID_KEYSTORE if (!strncmp(vpninfo->cert, "keystore:", 9)) { BIO *b = BIO_from_keystore(vpninfo, vpninfo->cert); if (!b) return -EINVAL; vpninfo->cert_x509 = PEM_read_bio_X509_AUX(b, NULL, pem_pw_cb, vpninfo); BIO_free(b); if (!vpninfo->cert_x509) { vpn_progress(vpninfo, PRG_ERR, _("Failed to load X509 certificate from keystore\n")); openconnect_report_ssl_errors(vpninfo); return -EINVAL; } if (!SSL_CTX_use_certificate(vpninfo->https_ctx, vpninfo->cert_x509)) { vpn_progress(vpninfo, PRG_ERR, _("Failed to use X509 certificate from keystore\n")); openconnect_report_ssl_errors(vpninfo); X509_free(vpninfo->cert_x509); vpninfo->cert_x509 = NULL; return -EINVAL; } } else #endif /* ANDROID_KEYSTORE */ { if (!SSL_CTX_use_certificate_chain_file(vpninfo->https_ctx, vpninfo->cert)) { vpn_progress(vpninfo, PRG_ERR, _("Loading certificate failed\n")); openconnect_report_ssl_errors(vpninfo); return -EINVAL; } /* Ew, we can't get it back from the OpenSSL CTX in any sane fashion */ reload_pem_cert(vpninfo); } #ifdef ANDROID_KEYSTORE if (!strncmp(vpninfo->sslkey, "keystore:", 9)) { EVP_PKEY *key; BIO *b; again_android: b = BIO_from_keystore(vpninfo, vpninfo->sslkey); if (!b) return -EINVAL; key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, vpninfo); BIO_free(b); if (!key) { if (is_pem_password_error(vpninfo)) goto again_android; return -EINVAL; } if (!SSL_CTX_use_PrivateKey(vpninfo->https_ctx, key)) { vpn_progress(vpninfo, PRG_ERR, _("Failed to use private key from keystore\n")); EVP_PKEY_free(key); X509_free(vpninfo->cert_x509); vpninfo->cert_x509 = NULL; return -EINVAL; } return 0; } #endif /* ANDROID_KEYSTORE */ if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) { FILE *f = fopen(vpninfo->sslkey, "r"); char buf[256]; if (!f) { vpn_progress(vpninfo, PRG_ERR, _("Failed to open private key file %s: %s\n"), vpninfo->cert, strerror(errno)); return -ENOENT; } buf[255] = 0; while (fgets(buf, 255, f)) { if (!strcmp(buf, "-----BEGIN TSS KEY BLOB-----\n")) { vpninfo->cert_type = CERT_TYPE_TPM; break; } else if (!strcmp(buf, "-----BEGIN RSA PRIVATE KEY-----\n") || !strcmp(buf, "-----BEGIN DSA PRIVATE KEY-----\n") || !strcmp(buf, "-----BEGIN ENCRYPTED PRIVATE KEY-----\n")) { vpninfo->cert_type = CERT_TYPE_PEM; break; } } fclose(f); if (vpninfo->cert_type == CERT_TYPE_UNKNOWN) { vpn_progress(vpninfo, PRG_ERR, _("Failed to identify private key type in '%s'\n"), vpninfo->sslkey); return -EINVAL; } } if (vpninfo->cert_type == CERT_TYPE_TPM) return load_tpm_certificate(vpninfo); /* Standard PEM certificate */ SSL_CTX_set_default_passwd_cb(vpninfo->https_ctx, pem_pw_cb); SSL_CTX_set_default_passwd_cb_userdata(vpninfo->https_ctx, vpninfo); again: if (!SSL_CTX_use_RSAPrivateKey_file(vpninfo->https_ctx, vpninfo->sslkey, SSL_FILETYPE_PEM)) { if (is_pem_password_error(vpninfo)) goto again; return -EINVAL; } return 0; }
int main(int argc, char **argv) { FILE *fp; EVP_PKEY *pkey = NULL; X509 *cert = NULL; STACK_OF(X509) *ca = NULL; PKCS12 *p12 = NULL; char *name = NULL; int i, ret = EXIT_FAILURE; if (argc != 4) { fprintf(stderr, "Usage: pkread p12file password opfile\n"); exit(EXIT_FAILURE); } if ((fp = fopen(argv[1], "rb")) == NULL) { fprintf(stderr, "Error opening file %s\n", argv[1]); exit(EXIT_FAILURE); } p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (p12 == NULL) { fprintf(stderr, "Error reading PKCS#12 file\n"); ERR_print_errors_fp(stderr); goto err; } if (!PKCS12_parse(p12, argv[2], &pkey, &cert, &ca)) { fprintf(stderr, "Error parsing PKCS#12 file\n"); ERR_print_errors_fp(stderr); goto err; } name = find_friendly_name(p12); PKCS12_free(p12); if ((fp = fopen(argv[3], "w")) == NULL) { fprintf(stderr, "Error opening file %s\n", argv[1]); goto err; } if (name != NULL) fprintf(fp, "***Friendly Name***\n%s\n", name); if (pkey != NULL) { fprintf(fp, "***Private Key***\n"); PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL); } if (cert != NULL) { fprintf(fp, "***User Certificate***\n"); PEM_write_X509_AUX(fp, cert); } if (ca != NULL && sk_X509_num(ca) > 0) { fprintf(fp, "***Other Certificates***\n"); for (i = 0; i < sk_X509_num(ca); i++) PEM_write_X509_AUX(fp, sk_X509_value(ca, i)); } fclose(fp); ret = EXIT_SUCCESS; err: OPENSSL_free(name); X509_free(cert); EVP_PKEY_free(pkey); sk_X509_pop_free(ca, X509_free); return ret; }