1 | /*
|
---|
2 | * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
5 | * this file except in compliance with the License. You can obtain a copy
|
---|
6 | * in the file LICENSE in the source distribution or at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | */
|
---|
9 |
|
---|
10 | #include <openssl/core_dispatch.h>
|
---|
11 | #include <openssl/pem.h>
|
---|
12 | #include <openssl/encoder.h>
|
---|
13 |
|
---|
14 | /*
|
---|
15 | * Selectors, named according to the ASN.1 names used throughout libcrypto.
|
---|
16 | *
|
---|
17 | * Note that these are not absolutely mandatory, they are rather a wishlist
|
---|
18 | * of sorts. The provider implementations are free to make choices that
|
---|
19 | * make sense for them, based on these selectors.
|
---|
20 | * For example, the EC backend is likely to really just output the private
|
---|
21 | * key to a PKCS#8 structure, even thought PEM_SELECTION_PrivateKey specifies
|
---|
22 | * the public key as well. This is fine, as long as the corresponding
|
---|
23 | * decoding operation can return an object that contains what libcrypto
|
---|
24 | * expects.
|
---|
25 | */
|
---|
26 | # define PEM_SELECTION_PUBKEY EVP_PKEY_PUBLIC_KEY
|
---|
27 | # define PEM_SELECTION_PrivateKey EVP_PKEY_KEYPAIR
|
---|
28 | # define PEM_SELECTION_Parameters EVP_PKEY_KEY_PARAMETERS
|
---|
29 |
|
---|
30 | /*
|
---|
31 | * Properties, named according to the ASN.1 names used throughout libcrypto.
|
---|
32 | */
|
---|
33 | # define PEM_STRUCTURE_PUBKEY "SubjectPublicKeyInfo"
|
---|
34 | # define PEM_STRUCTURE_PrivateKey "PrivateKeyInfo"
|
---|
35 | # define PEM_STRUCTURE_Parameters "type-specific"
|
---|
36 |
|
---|
37 | # define PEM_STRUCTURE_RSAPrivateKey "type-specific"
|
---|
38 | # define PEM_STRUCTURE_RSAPublicKey "type-specific"
|
---|
39 |
|
---|
40 | /* Alternative IMPLEMENT macros for provided encoders */
|
---|
41 |
|
---|
42 | # define IMPLEMENT_PEM_provided_write_body_vars(type, asn1, pq) \
|
---|
43 | int ret = 0; \
|
---|
44 | OSSL_ENCODER_CTX *ctx = \
|
---|
45 | OSSL_ENCODER_CTX_new_for_##type(x, PEM_SELECTION_##asn1, \
|
---|
46 | "PEM", PEM_STRUCTURE_##asn1, \
|
---|
47 | (pq)); \
|
---|
48 | \
|
---|
49 | if (OSSL_ENCODER_CTX_get_num_encoders(ctx) == 0) { \
|
---|
50 | OSSL_ENCODER_CTX_free(ctx); \
|
---|
51 | goto legacy; \
|
---|
52 | }
|
---|
53 | # define IMPLEMENT_PEM_provided_write_body_pass() \
|
---|
54 | ret = 1; \
|
---|
55 | if (kstr == NULL && cb == NULL) { \
|
---|
56 | if (u != NULL) { \
|
---|
57 | kstr = u; \
|
---|
58 | klen = strlen(u); \
|
---|
59 | } else { \
|
---|
60 | cb = PEM_def_callback; \
|
---|
61 | } \
|
---|
62 | } \
|
---|
63 | if (enc != NULL) { \
|
---|
64 | ret = 0; \
|
---|
65 | if (OSSL_ENCODER_CTX_set_cipher(ctx, EVP_CIPHER_get0_name(enc), \
|
---|
66 | NULL)) { \
|
---|
67 | ret = 1; \
|
---|
68 | if (kstr != NULL \
|
---|
69 | && !OSSL_ENCODER_CTX_set_passphrase(ctx, kstr, klen)) \
|
---|
70 | ret = 0; \
|
---|
71 | else if (cb != NULL \
|
---|
72 | && !OSSL_ENCODER_CTX_set_pem_password_cb(ctx, \
|
---|
73 | cb, u)) \
|
---|
74 | ret = 0; \
|
---|
75 | } \
|
---|
76 | } \
|
---|
77 | if (!ret) { \
|
---|
78 | OSSL_ENCODER_CTX_free(ctx); \
|
---|
79 | return 0; \
|
---|
80 | }
|
---|
81 | # define IMPLEMENT_PEM_provided_write_body_main(type, outtype) \
|
---|
82 | ret = OSSL_ENCODER_to_##outtype(ctx, out); \
|
---|
83 | OSSL_ENCODER_CTX_free(ctx); \
|
---|
84 | return ret
|
---|
85 | # define IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
|
---|
86 | writename) \
|
---|
87 | legacy: \
|
---|
88 | return PEM_ASN1_##writename((i2d_of_void *)i2d_##asn1, str, out, \
|
---|
89 | x, NULL, NULL, 0, NULL, NULL)
|
---|
90 | # define IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \
|
---|
91 | writename) \
|
---|
92 | legacy: \
|
---|
93 | return PEM_ASN1_##writename##((i2d_of_void *)i2d_##asn1, str, out, \
|
---|
94 | x, enc, kstr, klen, cb, u)
|
---|
95 |
|
---|
96 | # define IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, \
|
---|
97 | OUTTYPE, outtype, writename) \
|
---|
98 | PEM_write_fnsig(name, TYPE, OUTTYPE, writename) \
|
---|
99 | { \
|
---|
100 | IMPLEMENT_PEM_provided_write_body_vars(type, asn1, NULL); \
|
---|
101 | IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
|
---|
102 | IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
|
---|
103 | writename); \
|
---|
104 | } \
|
---|
105 | PEM_write_ex_fnsig(name, TYPE, OUTTYPE, writename) \
|
---|
106 | { \
|
---|
107 | IMPLEMENT_PEM_provided_write_body_vars(type, asn1, propq); \
|
---|
108 | IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
|
---|
109 | IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
|
---|
110 | writename); \
|
---|
111 | }
|
---|
112 |
|
---|
113 |
|
---|
114 | # define IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, \
|
---|
115 | OUTTYPE, outtype, writename) \
|
---|
116 | PEM_write_cb_fnsig(name, TYPE, OUTTYPE, writename) \
|
---|
117 | { \
|
---|
118 | IMPLEMENT_PEM_provided_write_body_vars(type, asn1, NULL); \
|
---|
119 | IMPLEMENT_PEM_provided_write_body_pass(); \
|
---|
120 | IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
|
---|
121 | IMPLEMENT_PEM_provided_write_body_fallback_cb(str, asn1, \
|
---|
122 | writename); \
|
---|
123 | } \
|
---|
124 | PEM_write_ex_cb_fnsig(name, TYPE, OUTTYPE, writename) \
|
---|
125 | { \
|
---|
126 | IMPLEMENT_PEM_provided_write_body_vars(type, asn1, propq); \
|
---|
127 | IMPLEMENT_PEM_provided_write_body_pass(); \
|
---|
128 | IMPLEMENT_PEM_provided_write_body_main(type, outtype); \
|
---|
129 | IMPLEMENT_PEM_provided_write_body_fallback(str, asn1, \
|
---|
130 | writename); \
|
---|
131 | }
|
---|
132 |
|
---|
133 | # ifdef OPENSSL_NO_STDIO
|
---|
134 |
|
---|
135 | # define IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1)
|
---|
136 | # define IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1)
|
---|
137 |
|
---|
138 | # else
|
---|
139 |
|
---|
140 | # define IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1) \
|
---|
141 | IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, FILE, fp, write)
|
---|
142 | # define IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1) \
|
---|
143 | IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, FILE, fp, write)
|
---|
144 |
|
---|
145 | # endif
|
---|
146 |
|
---|
147 | # define IMPLEMENT_PEM_provided_write_bio(name, TYPE, type, str, asn1) \
|
---|
148 | IMPLEMENT_PEM_provided_write_to(name, TYPE, type, str, asn1, BIO, bio, write_bio)
|
---|
149 | # define IMPLEMENT_PEM_provided_write_cb_bio(name, TYPE, type, str, asn1) \
|
---|
150 | IMPLEMENT_PEM_provided_write_cb_to(name, TYPE, type, str, asn1, BIO, bio, write_bio)
|
---|
151 |
|
---|
152 | # define IMPLEMENT_PEM_provided_write(name, TYPE, type, str, asn1) \
|
---|
153 | IMPLEMENT_PEM_provided_write_bio(name, TYPE, type, str, asn1) \
|
---|
154 | IMPLEMENT_PEM_provided_write_fp(name, TYPE, type, str, asn1)
|
---|
155 |
|
---|
156 | # define IMPLEMENT_PEM_provided_write_cb(name, TYPE, type, str, asn1) \
|
---|
157 | IMPLEMENT_PEM_provided_write_cb_bio(name, TYPE, type, str, asn1) \
|
---|
158 | IMPLEMENT_PEM_provided_write_cb_fp(name, TYPE, type, str, asn1)
|
---|
159 |
|
---|
160 | # define IMPLEMENT_PEM_provided_rw(name, TYPE, type, str, asn1) \
|
---|
161 | IMPLEMENT_PEM_read(name, TYPE, str, asn1) \
|
---|
162 | IMPLEMENT_PEM_provided_write(name, TYPE, type, str, asn1)
|
---|
163 |
|
---|
164 | # define IMPLEMENT_PEM_provided_rw_cb(name, TYPE, type, str, asn1) \
|
---|
165 | IMPLEMENT_PEM_read(name, TYPE, str, asn1) \
|
---|
166 | IMPLEMENT_PEM_provided_write_cb(name, TYPE, type, str, asn1)
|
---|
167 |
|
---|