/*
 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <openssl/pem.h>

#include <stdio.h>
#include <string.h>

#include <openssl/dh.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/pkcs8.h>
#include <openssl/rand.h>
#include <openssl/x509.h>

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;
}
