]>
Commit | Line | Data |
---|---|---|
4dde554c | 1 | /* |
fecb3aae | 2 | * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved. |
4dde554c DDO |
3 | * Copyright Nokia 2007-2019 |
4 | * Copyright Siemens AG 2015-2019 | |
5 | * | |
6 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
7 | * this file except in compliance with the License. You can obtain a copy | |
8 | * in the file LICENSE in the source distribution or at | |
9 | * https://www.openssl.org/source/license.html | |
10 | */ | |
11 | ||
12 | /* CMP functions for PKIHeader handling */ | |
13 | ||
14 | #include "cmp_local.h" | |
15 | ||
16 | #include <openssl/rand.h> | |
17 | ||
18 | /* explicit #includes not strictly needed since implied by the above: */ | |
19 | #include <openssl/asn1t.h> | |
20 | #include <openssl/cmp.h> | |
21 | #include <openssl/err.h> | |
22 | ||
23 | int ossl_cmp_hdr_set_pvno(OSSL_CMP_PKIHEADER *hdr, int pvno) | |
24 | { | |
25 | if (!ossl_assert(hdr != NULL)) | |
26 | return 0; | |
27 | return ASN1_INTEGER_set(hdr->pvno, pvno); | |
28 | } | |
29 | ||
30 | int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr) | |
31 | { | |
32 | int64_t pvno; | |
33 | ||
34 | if (!ossl_assert(hdr != NULL)) | |
35 | return -1; | |
36 | if (!ASN1_INTEGER_get_int64(&pvno, hdr->pvno) || pvno < 0 || pvno > INT_MAX) | |
37 | return -1; | |
38 | return (int)pvno; | |
39 | } | |
40 | ||
12bbcee2 DDO |
41 | int ossl_cmp_hdr_get_protection_nid(const OSSL_CMP_PKIHEADER *hdr) |
42 | { | |
43 | if (!ossl_assert(hdr != NULL) | |
44 | || hdr->protectionAlg == NULL) | |
45 | return NID_undef; | |
46 | return OBJ_obj2nid(hdr->protectionAlg->algorithm); | |
47 | } | |
48 | ||
143be474 DDO |
49 | ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const |
50 | OSSL_CMP_PKIHEADER *hdr) | |
4dde554c DDO |
51 | { |
52 | if (hdr == NULL) { | |
9311d0c4 | 53 | ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); |
4dde554c DDO |
54 | return NULL; |
55 | } | |
56 | return hdr->transactionID; | |
57 | } | |
58 | ||
59 | ASN1_OCTET_STRING *ossl_cmp_hdr_get0_senderNonce(const OSSL_CMP_PKIHEADER *hdr) | |
60 | { | |
61 | if (!ossl_assert(hdr != NULL)) | |
62 | return NULL; | |
63 | return hdr->senderNonce; | |
64 | } | |
65 | ||
66 | ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr) | |
67 | { | |
68 | if (hdr == NULL) { | |
9311d0c4 | 69 | ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); |
4dde554c DDO |
70 | return NULL; |
71 | } | |
72 | return hdr->recipNonce; | |
73 | } | |
74 | ||
7c6577ba DDO |
75 | STACK_OF(OSSL_CMP_ITAV) |
76 | *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr) | |
77 | { | |
78 | if (hdr == NULL) { | |
79 | ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); | |
80 | return NULL; | |
81 | } | |
82 | return hdr->generalInfo; | |
83 | } | |
84 | ||
dd5fa5f5 | 85 | /* a NULL-DN as an empty sequence of RDNs */ |
cfca56df DDO |
86 | int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name) |
87 | { | |
dd5fa5f5 DDO |
88 | return name == NULL |
89 | || (name->type == GEN_DIRNAME && IS_NULL_DN(name->d.directoryName)); | |
cfca56df DDO |
90 | } |
91 | ||
4dde554c DDO |
92 | /* |
93 | * Set the sender name in PKIHeader. | |
94 | * when nm is NULL, sender is set to an empty string | |
95 | * returns 1 on success, 0 on error | |
96 | */ | |
97 | int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm) | |
98 | { | |
99 | if (!ossl_assert(hdr != NULL)) | |
100 | return 0; | |
40a200f9 | 101 | return GENERAL_NAME_set1_X509_NAME(&hdr->sender, nm); |
4dde554c DDO |
102 | } |
103 | ||
104 | int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm) | |
105 | { | |
106 | if (!ossl_assert(hdr != NULL)) | |
107 | return 0; | |
40a200f9 | 108 | return GENERAL_NAME_set1_X509_NAME(&hdr->recipient, nm); |
4dde554c DDO |
109 | } |
110 | ||
111 | int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr) | |
112 | { | |
113 | if (!ossl_assert(hdr != NULL)) | |
114 | return 0; | |
115 | if (hdr->messageTime == NULL | |
116 | && (hdr->messageTime = ASN1_GENERALIZEDTIME_new()) == NULL) | |
117 | return 0; | |
118 | return ASN1_GENERALIZEDTIME_set(hdr->messageTime, time(NULL)) != NULL; | |
119 | } | |
120 | ||
1930b586 DDO |
121 | /* assign to *tgt a random byte array of given length */ |
122 | static int set_random(ASN1_OCTET_STRING **tgt, OSSL_CMP_CTX *ctx, size_t len) | |
4dde554c | 123 | { |
1930b586 | 124 | unsigned char *bytes = OPENSSL_malloc(len); |
4dde554c DDO |
125 | int res = 0; |
126 | ||
5cbd2ea3 | 127 | if (bytes == NULL || RAND_bytes_ex(ctx->libctx, bytes, len, 0) <= 0) |
9311d0c4 | 128 | ERR_raise(ERR_LIB_CMP, CMP_R_FAILURE_OBTAINING_RANDOM); |
1930b586 | 129 | else |
4dde554c | 130 | res = ossl_cmp_asn1_octet_string_set1_bytes(tgt, bytes, len); |
4dde554c DDO |
131 | OPENSSL_free(bytes); |
132 | return res; | |
133 | } | |
134 | ||
135 | int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr, | |
136 | const ASN1_OCTET_STRING *senderKID) | |
137 | { | |
138 | if (!ossl_assert(hdr != NULL)) | |
139 | return 0; | |
140 | return ossl_cmp_asn1_octet_string_set1(&hdr->senderKID, senderKID); | |
141 | } | |
142 | ||
143 | /* push the given text string to the given PKIFREETEXT ft */ | |
4dde554c DDO |
144 | int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text) |
145 | { | |
146 | if (!ossl_assert(hdr != NULL && text != NULL)) | |
147 | return 0; | |
148 | ||
149 | if (hdr->freeText == NULL | |
150 | && (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL) | |
151 | return 0; | |
152 | ||
153 | return sk_ASN1_UTF8STRING_push(hdr->freeText, text); | |
154 | } | |
155 | ||
156 | int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text) | |
157 | { | |
158 | if (!ossl_assert(hdr != NULL && text != NULL)) | |
159 | return 0; | |
160 | ||
161 | if (hdr->freeText == NULL | |
162 | && (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL) | |
163 | return 0; | |
164 | ||
62dcd2aa | 165 | return |
95f8c1e1 MC |
166 | ossl_cmp_sk_ASN1_UTF8STRING_push_str(hdr->freeText, (char *)text->data, |
167 | text->length); | |
4dde554c DDO |
168 | } |
169 | ||
170 | int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr, | |
171 | OSSL_CMP_ITAV *itav) | |
172 | { | |
173 | if (!ossl_assert(hdr != NULL && itav != NULL)) | |
174 | return 0; | |
175 | return OSSL_CMP_ITAV_push0_stack_item(&hdr->generalInfo, itav); | |
176 | } | |
177 | ||
178 | int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr, | |
62dcd2aa | 179 | const STACK_OF(OSSL_CMP_ITAV) *itavs) |
4dde554c DDO |
180 | { |
181 | int i; | |
182 | OSSL_CMP_ITAV *itav; | |
183 | ||
184 | if (!ossl_assert(hdr != NULL)) | |
185 | return 0; | |
186 | ||
187 | for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) { | |
188 | itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i)); | |
189 | if (itav == NULL) | |
190 | return 0; | |
191 | ||
192 | if (!ossl_cmp_hdr_generalInfo_push0_item(hdr, itav)) { | |
193 | OSSL_CMP_ITAV_free(itav); | |
194 | return 0; | |
195 | } | |
196 | } | |
197 | return 1; | |
198 | } | |
199 | ||
200 | int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr) | |
201 | { | |
202 | OSSL_CMP_ITAV *itav; | |
203 | ASN1_TYPE *asn1null; | |
204 | ||
205 | if (!ossl_assert(hdr != NULL)) | |
206 | return 0; | |
207 | asn1null = (ASN1_TYPE *)ASN1_NULL_new(); | |
208 | if (asn1null == NULL) | |
209 | return 0; | |
210 | if ((itav = OSSL_CMP_ITAV_create(OBJ_nid2obj(NID_id_it_implicitConfirm), | |
211 | asn1null)) == NULL) | |
212 | goto err; | |
213 | if (!ossl_cmp_hdr_generalInfo_push0_item(hdr, itav)) | |
214 | goto err; | |
215 | return 1; | |
216 | ||
217 | err: | |
218 | ASN1_TYPE_free(asn1null); | |
219 | OSSL_CMP_ITAV_free(itav); | |
220 | return 0; | |
221 | } | |
222 | ||
223 | /* return 1 if implicitConfirm in the generalInfo field of the header is set */ | |
62dcd2aa | 224 | int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr) |
4dde554c DDO |
225 | { |
226 | int itavCount; | |
227 | int i; | |
228 | OSSL_CMP_ITAV *itav; | |
229 | ||
230 | if (!ossl_assert(hdr != NULL)) | |
231 | return 0; | |
232 | ||
233 | itavCount = sk_OSSL_CMP_ITAV_num(hdr->generalInfo); | |
234 | for (i = 0; i < itavCount; i++) { | |
235 | itav = sk_OSSL_CMP_ITAV_value(hdr->generalInfo, i); | |
236 | if (itav != NULL | |
237 | && OBJ_obj2nid(itav->infoType) == NID_id_it_implicitConfirm) | |
238 | return 1; | |
239 | } | |
240 | ||
241 | return 0; | |
242 | } | |
243 | ||
143be474 DDO |
244 | /* |
245 | * set ctx->transactionID in CMP header | |
246 | * if ctx->transactionID is NULL, a random one is created with 128 bit | |
247 | * according to section 5.1.1: | |
248 | * | |
249 | * It is RECOMMENDED that the clients fill the transactionID field with | |
250 | * 128 bits of (pseudo-) random data for the start of a transaction to | |
251 | * reduce the probability of having the transactionID in use at the server. | |
252 | */ | |
253 | int ossl_cmp_hdr_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr) | |
254 | { | |
dd5fa5f5 DDO |
255 | if (ctx->transactionID == NULL) { |
256 | char *tid; | |
257 | ||
258 | if (!set_random(&ctx->transactionID, ctx, | |
259 | OSSL_CMP_TRANSACTIONID_LENGTH)) | |
260 | return 0; | |
a3ea35c2 | 261 | tid = i2s_ASN1_OCTET_STRING(NULL, ctx->transactionID); |
dd5fa5f5 DDO |
262 | if (tid != NULL) |
263 | ossl_cmp_log1(DEBUG, ctx, | |
264 | "Starting new transaction with ID=%s", tid); | |
265 | OPENSSL_free(tid); | |
266 | } | |
267 | ||
143be474 DDO |
268 | return ossl_cmp_asn1_octet_string_set1(&hdr->transactionID, |
269 | ctx->transactionID); | |
270 | } | |
271 | ||
4dde554c DDO |
272 | /* fill in all fields of the hdr according to the info given in ctx */ |
273 | int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr) | |
274 | { | |
8cc86b81 DDO |
275 | const X509_NAME *sender; |
276 | const X509_NAME *rcp = NULL; | |
4dde554c DDO |
277 | |
278 | if (!ossl_assert(ctx != NULL && hdr != NULL)) | |
279 | return 0; | |
280 | ||
281 | /* set the CMP version */ | |
282 | if (!ossl_cmp_hdr_set_pvno(hdr, OSSL_CMP_PVNO)) | |
283 | return 0; | |
284 | ||
4dde554c | 285 | /* |
cd7ec0bc | 286 | * If no protection cert nor oldCert nor CSR nor subject is given, |
16931355 | 287 | * sender name is not known to the client and thus set to NULL-DN |
4dde554c | 288 | */ |
16931355 DDO |
289 | sender = ctx->cert != NULL ? X509_get_subject_name(ctx->cert) : |
290 | ctx->oldCert != NULL ? X509_get_subject_name(ctx->oldCert) : | |
cd7ec0bc | 291 | ctx->p10CSR != NULL ? X509_REQ_get_subject_name(ctx->p10CSR) : |
16931355 | 292 | ctx->subjectName; |
4dde554c DDO |
293 | if (!ossl_cmp_hdr_set1_sender(hdr, sender)) |
294 | return 0; | |
295 | ||
296 | /* determine recipient entry in PKIHeader */ | |
b27ff9b8 | 297 | if (ctx->recipient != NULL) |
4dde554c | 298 | rcp = ctx->recipient; |
b27ff9b8 DDO |
299 | else if (ctx->srvCert != NULL) |
300 | rcp = X509_get_subject_name(ctx->srvCert); | |
301 | else if (ctx->issuer != NULL) | |
4dde554c | 302 | rcp = ctx->issuer; |
b27ff9b8 | 303 | else if (ctx->oldCert != NULL) |
4dde554c | 304 | rcp = X509_get_issuer_name(ctx->oldCert); |
b27ff9b8 | 305 | else if (ctx->cert != NULL) |
63f1883d | 306 | rcp = X509_get_issuer_name(ctx->cert); |
4dde554c DDO |
307 | if (!ossl_cmp_hdr_set1_recipient(hdr, rcp)) |
308 | return 0; | |
309 | ||
310 | /* set current time as message time */ | |
311 | if (!ossl_cmp_hdr_update_messageTime(hdr)) | |
312 | return 0; | |
313 | ||
314 | if (ctx->recipNonce != NULL | |
315 | && !ossl_cmp_asn1_octet_string_set1(&hdr->recipNonce, | |
316 | ctx->recipNonce)) | |
317 | return 0; | |
318 | ||
143be474 | 319 | if (!ossl_cmp_hdr_set_transactionID(ctx, hdr)) |
4dde554c DDO |
320 | return 0; |
321 | ||
322 | /*- | |
323 | * set random senderNonce | |
324 | * according to section 5.1.1: | |
325 | * | |
326 | * senderNonce present | |
327 | * -- 128 (pseudo-)random bits | |
328 | * The senderNonce and recipNonce fields protect the PKIMessage against | |
329 | * replay attacks. The senderNonce will typically be 128 bits of | |
330 | * (pseudo-) random data generated by the sender, whereas the recipNonce | |
331 | * is copied from the senderNonce of the previous message in the | |
332 | * transaction. | |
333 | */ | |
1930b586 | 334 | if (!set_random(&hdr->senderNonce, ctx, OSSL_CMP_SENDERNONCE_LENGTH)) |
4dde554c DDO |
335 | return 0; |
336 | ||
337 | /* store senderNonce - for cmp with recipNonce in next outgoing msg */ | |
338 | if (!OSSL_CMP_CTX_set1_senderNonce(ctx, hdr->senderNonce)) | |
339 | return 0; | |
340 | ||
341 | /*- | |
342 | * freeText [7] PKIFreeText OPTIONAL, | |
343 | * -- this may be used to indicate context-specific instructions | |
344 | * -- (this field is intended for human consumption) | |
345 | */ | |
346 | if (ctx->freeText != NULL | |
347 | && !ossl_cmp_hdr_push1_freeText(hdr, ctx->freeText)) | |
348 | return 0; | |
349 | ||
350 | return 1; | |
351 | } |