// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include #include #include #include EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u) { char *nm = NULL; const unsigned char *p = NULL; unsigned char *data = NULL; long len; EVP_PKEY *ret = NULL; if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) { return NULL; } p = data; if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { PKCS8_PRIV_KEY_INFO *p8inf; p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); if (!p8inf) { goto p8err; } ret = EVP_PKCS82PKEY(p8inf); if (x) { if (*x) { EVP_PKEY_free((EVP_PKEY *)*x); } *x = ret; } PKCS8_PRIV_KEY_INFO_free(p8inf); } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { PKCS8_PRIV_KEY_INFO *p8inf; X509_SIG *p8; int pass_len; char psbuf[PEM_BUFSIZE]; p8 = d2i_X509_SIG(NULL, &p, len); if (!p8) { goto p8err; } pass_len = 0; if (!cb) { cb = PEM_def_callback; } pass_len = cb(psbuf, PEM_BUFSIZE, 0, u); if (pass_len < 0) { OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); X509_SIG_free(p8); goto err; } p8inf = PKCS8_decrypt(p8, psbuf, pass_len); X509_SIG_free(p8); OPENSSL_cleanse(psbuf, pass_len); if (!p8inf) { goto p8err; } ret = EVP_PKCS82PKEY(p8inf); if (x) { if (*x) { EVP_PKEY_free((EVP_PKEY *)*x); } *x = ret; } PKCS8_PRIV_KEY_INFO_free(p8inf); } else if (strcmp(nm, PEM_STRING_RSA) == 0) { // TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the // standalone format. This and the cases below probably should not // accept PKCS#8. ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len); } else if (strcmp(nm, PEM_STRING_EC) == 0) { ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len); } else if (strcmp(nm, PEM_STRING_DSA) == 0) { ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len); } p8err: if (ret == NULL) { OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); } err: OPENSSL_free(nm); OPENSSL_free(data); return ret; } int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, const unsigned char *pass, int pass_len, pem_password_cb *cb, void *u) { return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (const char *)pass, pass_len, cb, u); } EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u) { BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); if (b == NULL) { OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); return NULL; } EVP_PKEY *ret = PEM_read_bio_PrivateKey(b, x, cb, u); BIO_free(b); return ret; } int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, const unsigned char *pass, int pass_len, pem_password_cb *cb, void *u) { BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); if (b == NULL) { OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); return 0; } int ret = PEM_write_bio_PrivateKey(b, x, enc, pass, pass_len, cb, u); BIO_free(b); return ret; }