Decoding PKCS#8: separate decoding of encrypted and unencrypted PKCS#8
[openssl.git] / providers / implementations / encode_decode / encode_key2any.c
index f986ec124e796c7e88b1c7bd8384e31669a59a67..855866cbfe2ce9c611546001e131659264d2d7d7 100644 (file)
@@ -128,12 +128,14 @@ static X509_SIG *key_to_encp8(const void *key, int key_nid,
 {
     PKCS8_PRIV_KEY_INFO *p8info =
         key_to_p8info(key, key_nid, params, params_type, k2d);
-    X509_SIG *p8 = p8info_to_encp8(p8info, ctx);
+    X509_SIG *p8 = NULL;
 
-    if (p8info == NULL)
+    if (p8info == NULL) {
         free_asn1_data(params_type, params);
-
-    PKCS8_PRIV_KEY_INFO_free(p8info);
+    } else {
+        p8 = p8info_to_encp8(p8info, ctx);
+        PKCS8_PRIV_KEY_INFO_free(p8info);
+    }
     return p8;
 }
 
@@ -162,81 +164,141 @@ static X509_PUBKEY *key_to_pubkey(const void *key, int key_nid,
 }
 
 /*
- * key_to_pkcs8_* produce encoded output with the key data pkcs8
- * in a structure.  For private keys, that structure is PKCS#8, and for
- * public keys, it's X.509 SubjectPublicKeyInfo.  Parameters don't have
- * any defined envelopment of that kind.
+ * key_to_epki_* produce encoded output with the private key data in a
+ * EncryptedPrivateKeyInfo structure (defined by PKCS#8).  They require
+ * that there's an intent to encrypt, anything else is an error.
+ * They are currently only called from the corresponding key_to_pki_ function.
+ *
+ * key_to_pki_* primarly produce encoded output with the private key data
+ * in a PrivateKeyInfo structure (also defined by PKCS#8).  However, if
+ * there is an intent to encrypt the data, the corresponding key_to_epki_*
+ * function is used instead.
+ *
+ * key_to_spki_* produce encoded output with the public key data in an
+ * X.509 SubjectPublicKeyInfo.
+ *
+ * Key parameters don't have any defined envelopment of this kind, but are
+ * included in some manner in the output from the functions described above,
+ * either in the AlgorithmIdentifier's parameter field, or as part of the
+ * key data itself.
  */
-static int key_to_pkcs8_der_priv_bio(BIO *out, const void *key,
-                                     int key_nid,
-                                     ossl_unused const char *pemname,
-                                     key_to_paramstring_fn *p2s,
-                                     i2d_of_void *k2d,
-                                     struct key2any_ctx_st *ctx)
+
+static int key_to_epki_der_priv_bio(BIO *out, const void *key,
+                                    int key_nid,
+                                    ossl_unused const char *pemname,
+                                    key_to_paramstring_fn *p2s,
+                                    i2d_of_void *k2d,
+                                    struct key2any_ctx_st *ctx)
 {
     int ret = 0;
     void *str = NULL;
     int strtype = V_ASN1_UNDEF;
+    X509_SIG *p8;
+
+    if (!ctx->cipher_intent)
+        return 0;
 
     if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
                             &str, &strtype))
         return 0;
 
-    if (ctx->cipher_intent) {
-        X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx);
+    p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx);
+    if (p8 != NULL)
+        ret = i2d_PKCS8_bio(out, p8);
 
-        if (p8 != NULL)
-            ret = i2d_PKCS8_bio(out, p8);
+    X509_SIG_free(p8);
 
-        X509_SIG_free(p8);
-    } else {
-        PKCS8_PRIV_KEY_INFO *p8info =
-            key_to_p8info(key, key_nid, str, strtype, k2d);
+    return ret;
+}
 
-        if (p8info != NULL)
-            ret = i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8info);
-        else
-            free_asn1_data(strtype, str);
+static int key_to_epki_pem_priv_bio(BIO *out, const void *key,
+                                    int key_nid,
+                                    ossl_unused const char *pemname,
+                                    key_to_paramstring_fn *p2s,
+                                    i2d_of_void *k2d,
+                                    struct key2any_ctx_st *ctx)
+{
+    int ret = 0;
+    void *str = NULL;
+    int strtype = V_ASN1_UNDEF;
+    X509_SIG *p8;
 
-        PKCS8_PRIV_KEY_INFO_free(p8info);
-    }
+    if (!ctx->cipher_intent)
+        return 0;
+
+    if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
+                            &str, &strtype))
+        return 0;
+
+    p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx);
+    if (p8 != NULL)
+        ret = PEM_write_bio_PKCS8(out, p8);
+
+    X509_SIG_free(p8);
 
     return ret;
 }
 
-static int key_to_pkcs8_pem_priv_bio(BIO *out, const void *key,
-                                     int key_nid,
-                                     ossl_unused const char *pemname,
-                                     key_to_paramstring_fn *p2s,
-                                     i2d_of_void *k2d,
-                                     struct key2any_ctx_st *ctx)
+static int key_to_pki_der_priv_bio(BIO *out, const void *key,
+                                   int key_nid,
+                                   ossl_unused const char *pemname,
+                                   key_to_paramstring_fn *p2s,
+                                   i2d_of_void *k2d,
+                                   struct key2any_ctx_st *ctx)
 {
     int ret = 0;
     void *str = NULL;
     int strtype = V_ASN1_UNDEF;
+    PKCS8_PRIV_KEY_INFO *p8info;
+
+    if (ctx->cipher_intent)
+        return key_to_epki_der_priv_bio(out, key, key_nid, pemname,
+                                        p2s, k2d, ctx);
 
     if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
                             &str, &strtype))
         return 0;
 
-    if (ctx->cipher_intent) {
-        X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx);
+    p8info = key_to_p8info(key, key_nid, str, strtype, k2d);
 
-        if (p8 != NULL)
-            ret = PEM_write_bio_PKCS8(out, p8);
+    if (p8info != NULL)
+        ret = i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8info);
+    else
+        free_asn1_data(strtype, str);
 
-        X509_SIG_free(p8);
-    } else {
-        PKCS8_PRIV_KEY_INFO *p8info =
-            key_to_p8info(key, key_nid, str, strtype, k2d);
+    PKCS8_PRIV_KEY_INFO_free(p8info);
 
-        if (p8info != NULL)
-            ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8info);
-        else
-            free_asn1_data(strtype, str);
+    return ret;
+}
 
-        PKCS8_PRIV_KEY_INFO_free(p8info);
-    }
+static int key_to_pki_pem_priv_bio(BIO *out, const void *key,
+                                   int key_nid,
+                                   ossl_unused const char *pemname,
+                                   key_to_paramstring_fn *p2s,
+                                   i2d_of_void *k2d,
+                                   struct key2any_ctx_st *ctx)
+{
+    int ret = 0;
+    void *str = NULL;
+    int strtype = V_ASN1_UNDEF;
+    PKCS8_PRIV_KEY_INFO *p8info;
+
+    if (ctx->cipher_intent)
+        return key_to_epki_pem_priv_bio(out, key, key_nid, pemname,
+                                        p2s, k2d, ctx);
+
+    if (p2s != NULL && !p2s(key, key_nid, ctx->save_parameters,
+                            &str, &strtype))
+        return 0;
+
+    p8info = key_to_p8info(key, key_nid, str, strtype, k2d);
+
+    if (p8info != NULL)
+        ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8info);
+    else
+        free_asn1_data(strtype, str);
+
+    PKCS8_PRIV_KEY_INFO_free(p8info);
 
     return ret;
 }
@@ -427,7 +489,7 @@ static int dh_spki_pub_to_der(const void *dh, unsigned char **pder)
     return ret;
 }
 
-static int dh_pkcs8_priv_to_der(const void *dh, unsigned char **pder)
+static int dh_pki_priv_to_der(const void *dh, unsigned char **pder)
 {
     const BIGNUM *bn = NULL;
     ASN1_INTEGER *priv_key = NULL;
@@ -540,7 +602,7 @@ static int dsa_spki_pub_to_der(const void *dsa, unsigned char **pder)
     return ret;
 }
 
-static int dsa_pkcs8_priv_to_der(const void *dsa, unsigned char **pder)
+static int dsa_pki_priv_to_der(const void *dsa, unsigned char **pder)
 {
     const BIGNUM *bn = NULL;
     ASN1_INTEGER *priv_key = NULL;
@@ -639,7 +701,7 @@ static int ec_spki_pub_to_der(const void *eckey, unsigned char **pder)
     return i2o_ECPublicKey(eckey, pder);
 }
 
-static int ec_pkcs8_priv_to_der(const void *veckey, unsigned char **pder)
+static int ec_pki_priv_to_der(const void *veckey, unsigned char **pder)
 {
     EC_KEY *eckey = (EC_KEY *)veckey;
     unsigned int old_flags;
@@ -700,7 +762,7 @@ static int ecx_spki_pub_to_der(const void *vecxkey, unsigned char **pder)
     return ecxkey->keylen;
 }
 
-static int ecx_pkcs8_priv_to_der(const void *vecxkey, unsigned char **pder)
+static int ecx_pki_priv_to_der(const void *vecxkey, unsigned char **pder)
 {
     const ECX_KEY *ecxkey = vecxkey;
     ASN1_OCTET_STRING oct;
@@ -826,7 +888,7 @@ static int prepare_rsa_params(const void *rsa, int nid, int save,
  * RSA is extremely simple, as PKCS#1 is used for the PKCS#8 |privateKey|
  * field as well as the SubjectPublicKeyInfo |subjectPublicKey| field.
  */
-#define rsa_pkcs8_priv_to_der           rsa_type_specific_priv_to_der
+#define rsa_pki_priv_to_der             rsa_type_specific_priv_to_der
 #define rsa_spki_pub_to_der             rsa_type_specific_pub_to_der
 #define rsa_type_specific_priv_to_der   (i2d_of_void *)i2d_RSAPrivateKey
 #define rsa_type_specific_pub_to_der    (i2d_of_void *)i2d_RSAPublicKey
@@ -1041,10 +1103,18 @@ static int key2any_encode(struct key2any_ctx_st *ctx, OSSL_CORE_BIO *cout,
  *      the same.
  */
 
-/* PKCS#8 is a structure for private keys only */
-#define DO_PKCS8_selection_mask DO_PRIVATE_KEY_selection_mask
-#define DO_PKCS8(impl, type, output)                                        \
-    DO_PRIVATE_KEY(impl, type, pkcs8, output)
+/*
+ * PKCS#8 defines two structures for private keys only:
+ * - PrivateKeyInfo             (raw unencrypted form)
+ * - EncryptedPrivateKeyInfo    (encrypted wrapping)
+ *
+ * To allow a certain amount of flexibility, we allow the routines
+ * for PrivateKeyInfo to also produce EncryptedPrivateKeyInfo if a
+ * passphrase callback has been passed to them.
+ */
+#define DO_PrivateKeyInfo_selection_mask DO_PRIVATE_KEY_selection_mask
+#define DO_PrivateKeyInfo(impl, type, output)                               \
+    DO_PRIVATE_KEY(impl, type, pki, output)
 
 /* SubjectPublicKeyInfo is a structure for public keys only */
 #define DO_SubjectPublicKeyInfo_selection_mask DO_PUBLIC_KEY_selection_mask
@@ -1258,55 +1328,55 @@ MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, type_specific_no_pub, pem);
  * For PEM, these are expected to be used by PEM_write_bio_PrivateKey(),
  * PEM_write_bio_PUBKEY() and PEM_write_bio_Parameters().
  */
-MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PKCS8, der);
-MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PKCS8, pem);
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PrivateKeyInfo, der);
+MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, PrivateKeyInfo, pem);
 MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(rsa, rsa, EVP_PKEY_RSA, SubjectPublicKeyInfo, pem);
-MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PKCS8, der);
-MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PKCS8, pem);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PrivateKeyInfo, der);
+MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, PrivateKeyInfo, pem);
 MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(rsapss, rsa, EVP_PKEY_RSA_PSS, SubjectPublicKeyInfo, pem);
 #ifndef OPENSSL_NO_DH
-MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PKCS8, der);
-MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PKCS8, pem);
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PrivateKeyInfo, der);
+MAKE_ENCODER(dh, dh, EVP_PKEY_DH, PrivateKeyInfo, pem);
 MAKE_ENCODER(dh, dh, EVP_PKEY_DH, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(dh, dh, EVP_PKEY_DH, SubjectPublicKeyInfo, pem);
-MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PKCS8, der);
-MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PKCS8, pem);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PrivateKeyInfo, der);
+MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, PrivateKeyInfo, pem);
 MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(dhx, dh, EVP_PKEY_DHX, SubjectPublicKeyInfo, pem);
 #endif
 #ifndef OPENSSL_NO_DSA
-MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PKCS8, der);
-MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PKCS8, pem);
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PrivateKeyInfo, der);
+MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, PrivateKeyInfo, pem);
 MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(dsa, dsa, EVP_PKEY_DSA, SubjectPublicKeyInfo, pem);
 #endif
 #ifndef OPENSSL_NO_EC
-MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PKCS8, der);
-MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PKCS8, pem);
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PrivateKeyInfo, der);
+MAKE_ENCODER(ec, ec, EVP_PKEY_EC, PrivateKeyInfo, pem);
 MAKE_ENCODER(ec, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(ec, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, pem);
 # ifndef OPENSSL_NO_SM2
-MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PKCS8, der);
-MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PKCS8, pem);
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PrivateKeyInfo, der);
+MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, PrivateKeyInfo, pem);
 MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(sm2, ec, EVP_PKEY_EC, SubjectPublicKeyInfo, pem);
 # endif
-MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PKCS8, der);
-MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PKCS8, pem);
+MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PrivateKeyInfo, der);
+MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, PrivateKeyInfo, pem);
 MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(ed25519, ecx, EVP_PKEY_ED25519, SubjectPublicKeyInfo, pem);
-MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PKCS8, der);
-MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PKCS8, pem);
+MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, der);
+MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, pem);
 MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(ed448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, pem);
-MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PKCS8, der);
-MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PKCS8, pem);
+MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PrivateKeyInfo, der);
+MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, PrivateKeyInfo, pem);
 MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(x25519, ecx, EVP_PKEY_X25519, SubjectPublicKeyInfo, pem);
-MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PKCS8, der);
-MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PKCS8, pem);
+MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, der);
+MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, PrivateKeyInfo, pem);
 MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(x448, ecx, EVP_PKEY_ED448, SubjectPublicKeyInfo, pem);
 #endif