Add i2d_PKCS12*.
This is not very useful without PKCS12_create, which a follow-up change
will implement.
Change-Id: I355ccd22a165830911ae189871ab90a6101f42ae
Reviewed-on: https://boringssl-review.googlesource.com/28327
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/pkcs8/pkcs8_x509.c b/crypto/pkcs8/pkcs8_x509.c
index b3e2d93..30b76c5 100644
--- a/crypto/pkcs8/pkcs8_x509.c
+++ b/crypto/pkcs8/pkcs8_x509.c
@@ -714,6 +714,55 @@
return ret;
}
+int i2d_PKCS12(const PKCS12 *p12, uint8_t **out) {
+ if (p12->ber_len > INT_MAX) {
+ OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
+ return -1;
+ }
+
+ if (out == NULL) {
+ return (int)p12->ber_len;
+ }
+
+ if (*out == NULL) {
+ *out = OPENSSL_malloc(p12->ber_len);
+ if (*out == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ OPENSSL_memcpy(*out, p12->ber_bytes, p12->ber_len);
+ } else {
+ OPENSSL_memcpy(*out, p12->ber_bytes, p12->ber_len);
+ *out += p12->ber_len;
+ }
+ return (int)p12->ber_len;
+}
+
+int i2d_PKCS12_bio(BIO *bio, const PKCS12 *p12) {
+ size_t written = 0;
+ while (written < p12->ber_len) {
+ size_t todo = p12->ber_len - written;
+ int len = todo > INT_MAX ? INT_MAX : (int)todo;
+ int ret = BIO_write(bio, p12->ber_bytes + written, len);
+ if (ret <= 0) {
+ return 0;
+ }
+ written += (size_t)ret;
+ }
+ return 1;
+}
+
+int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12) {
+ BIO *bio = BIO_new_fp(fp, 0 /* don't take ownership */);
+ if (bio == NULL) {
+ return 0;
+ }
+
+ int ret = i2d_PKCS12_bio(bio, p12);
+ BIO_free(bio);
+ return ret;
+}
+
int PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey,
X509 **out_cert, STACK_OF(X509) **out_ca_certs) {
CBS ber_bytes;
diff --git a/include/openssl/pkcs8.h b/include/openssl/pkcs8.h
index f84906f..05c635e 100644
--- a/include/openssl/pkcs8.h
+++ b/include/openssl/pkcs8.h
@@ -152,6 +152,20 @@
// d2i_PKCS12_fp acts like |d2i_PKCS12| but reads from a |FILE|.
OPENSSL_EXPORT PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12);
+// i2d_PKCS12 is a dummy function which copies the contents of |p12|. If |out|
+// is not NULL then the result is written to |*out| and |*out| is advanced just
+// past the output. It returns the number of bytes in the result, whether
+// written or not, or a negative value on error.
+OPENSSL_EXPORT int i2d_PKCS12(const PKCS12 *p12, uint8_t **out);
+
+// i2d_PKCS12_bio writes the contents of |p12| to |bio|. It returns one on
+// success and zero on error.
+OPENSSL_EXPORT int i2d_PKCS12_bio(BIO *bio, const PKCS12 *p12);
+
+// i2d_PKCS12_fp writes the contents of |p12| to |fp|. It returns one on
+// success and zero on error.
+OPENSSL_EXPORT int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12);
+
// PKCS12_parse calls |PKCS12_get_key_and_certs| on the ASN.1 data stored in
// |p12|. The |out_pkey| and |out_cert| arguments must not be NULL and, on
// successful exit, the private key and first certificate will be stored in