]>
Commit | Line | Data |
---|---|---|
4dde554c DDO |
1 | /* |
2 | * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. | |
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 | ||
41 | ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const OSSL_CMP_PKIHEADER *hdr) | |
42 | { | |
43 | if (hdr == NULL) { | |
44 | CMPerr(0, CMP_R_NULL_ARGUMENT); | |
45 | return NULL; | |
46 | } | |
47 | return hdr->transactionID; | |
48 | } | |
49 | ||
50 | ASN1_OCTET_STRING *ossl_cmp_hdr_get0_senderNonce(const OSSL_CMP_PKIHEADER *hdr) | |
51 | { | |
52 | if (!ossl_assert(hdr != NULL)) | |
53 | return NULL; | |
54 | return hdr->senderNonce; | |
55 | } | |
56 | ||
57 | ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr) | |
58 | { | |
59 | if (hdr == NULL) { | |
60 | CMPerr(0, CMP_R_NULL_ARGUMENT); | |
61 | return NULL; | |
62 | } | |
63 | return hdr->recipNonce; | |
64 | } | |
65 | ||
cfca56df DDO |
66 | int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name) |
67 | { | |
68 | X509_NAME *null = X509_NAME_new(); | |
69 | int res = name == NULL || null == NULL | |
70 | || (name->type == GEN_DIRNAME | |
71 | && X509_NAME_cmp(name->d.directoryName, null) == 0); | |
72 | ||
73 | X509_NAME_free(null); | |
74 | return res; | |
75 | } | |
76 | ||
4dde554c DDO |
77 | /* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */ |
78 | static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src) | |
79 | { | |
cfca56df | 80 | GENERAL_NAME *name; |
4dde554c DDO |
81 | |
82 | if (!ossl_assert(tgt != NULL)) | |
83 | return 0; | |
cfca56df | 84 | if ((name = GENERAL_NAME_new()) == NULL) |
4dde554c | 85 | goto err; |
cfca56df | 86 | name->type = GEN_DIRNAME; |
4dde554c DDO |
87 | |
88 | if (src == NULL) { /* NULL-DN */ | |
cfca56df | 89 | if ((name->d.directoryName = X509_NAME_new()) == NULL) |
4dde554c | 90 | goto err; |
cfca56df | 91 | } else if (!X509_NAME_set(&name->d.directoryName, src)) { |
4dde554c DDO |
92 | goto err; |
93 | } | |
94 | ||
95 | GENERAL_NAME_free(*tgt); | |
cfca56df | 96 | *tgt = name; |
4dde554c DDO |
97 | |
98 | return 1; | |
99 | ||
100 | err: | |
cfca56df | 101 | GENERAL_NAME_free(name); |
4dde554c DDO |
102 | return 0; |
103 | } | |
104 | ||
105 | /* | |
106 | * Set the sender name in PKIHeader. | |
107 | * when nm is NULL, sender is set to an empty string | |
108 | * returns 1 on success, 0 on error | |
109 | */ | |
110 | int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm) | |
111 | { | |
112 | if (!ossl_assert(hdr != NULL)) | |
113 | return 0; | |
114 | return set1_general_name(&hdr->sender, nm); | |
115 | } | |
116 | ||
117 | int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm) | |
118 | { | |
119 | if (!ossl_assert(hdr != NULL)) | |
120 | return 0; | |
121 | return set1_general_name(&hdr->recipient, nm); | |
122 | } | |
123 | ||
124 | int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr) | |
125 | { | |
126 | if (!ossl_assert(hdr != NULL)) | |
127 | return 0; | |
128 | if (hdr->messageTime == NULL | |
129 | && (hdr->messageTime = ASN1_GENERALIZEDTIME_new()) == NULL) | |
130 | return 0; | |
131 | return ASN1_GENERALIZEDTIME_set(hdr->messageTime, time(NULL)) != NULL; | |
132 | } | |
133 | ||
134 | /* assign to *tgt a copy of src (or if NULL a random byte array of given len) */ | |
135 | static int set1_aostr_else_random(ASN1_OCTET_STRING **tgt, | |
136 | const ASN1_OCTET_STRING *src, size_t len) | |
137 | { | |
138 | unsigned char *bytes = NULL; | |
139 | int res = 0; | |
140 | ||
141 | if (src == NULL) { /* generate a random value if src == NULL */ | |
142 | if ((bytes = OPENSSL_malloc(len)) == NULL) | |
143 | goto err; | |
144 | if (RAND_bytes(bytes, len) <= 0) { | |
145 | CMPerr(0, CMP_R_FAILURE_OBTAINING_RANDOM); | |
146 | goto err; | |
147 | } | |
148 | res = ossl_cmp_asn1_octet_string_set1_bytes(tgt, bytes, len); | |
149 | } else { | |
150 | res = ossl_cmp_asn1_octet_string_set1(tgt, src); | |
151 | } | |
152 | ||
153 | err: | |
154 | OPENSSL_free(bytes); | |
155 | return res; | |
156 | } | |
157 | ||
158 | int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr, | |
159 | const ASN1_OCTET_STRING *senderKID) | |
160 | { | |
161 | if (!ossl_assert(hdr != NULL)) | |
162 | return 0; | |
163 | return ossl_cmp_asn1_octet_string_set1(&hdr->senderKID, senderKID); | |
164 | } | |
165 | ||
166 | /* push the given text string to the given PKIFREETEXT ft */ | |
4dde554c DDO |
167 | int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text) |
168 | { | |
169 | if (!ossl_assert(hdr != NULL && text != NULL)) | |
170 | return 0; | |
171 | ||
172 | if (hdr->freeText == NULL | |
173 | && (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL) | |
174 | return 0; | |
175 | ||
176 | return sk_ASN1_UTF8STRING_push(hdr->freeText, text); | |
177 | } | |
178 | ||
179 | int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text) | |
180 | { | |
181 | if (!ossl_assert(hdr != NULL && text != NULL)) | |
182 | return 0; | |
183 | ||
184 | if (hdr->freeText == NULL | |
185 | && (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL) | |
186 | return 0; | |
187 | ||
62dcd2aa DDO |
188 | return |
189 | ossl_cmp_sk_ASN1_UTF8STRING_push_str(hdr->freeText, (char *)text->data); | |
4dde554c DDO |
190 | } |
191 | ||
192 | int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr, | |
193 | OSSL_CMP_ITAV *itav) | |
194 | { | |
195 | if (!ossl_assert(hdr != NULL && itav != NULL)) | |
196 | return 0; | |
197 | return OSSL_CMP_ITAV_push0_stack_item(&hdr->generalInfo, itav); | |
198 | } | |
199 | ||
200 | int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr, | |
62dcd2aa | 201 | const STACK_OF(OSSL_CMP_ITAV) *itavs) |
4dde554c DDO |
202 | { |
203 | int i; | |
204 | OSSL_CMP_ITAV *itav; | |
205 | ||
206 | if (!ossl_assert(hdr != NULL)) | |
207 | return 0; | |
208 | ||
209 | for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) { | |
210 | itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i)); | |
211 | if (itav == NULL) | |
212 | return 0; | |
213 | ||
214 | if (!ossl_cmp_hdr_generalInfo_push0_item(hdr, itav)) { | |
215 | OSSL_CMP_ITAV_free(itav); | |
216 | return 0; | |
217 | } | |
218 | } | |
219 | return 1; | |
220 | } | |
221 | ||
222 | int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr) | |
223 | { | |
224 | OSSL_CMP_ITAV *itav; | |
225 | ASN1_TYPE *asn1null; | |
226 | ||
227 | if (!ossl_assert(hdr != NULL)) | |
228 | return 0; | |
229 | asn1null = (ASN1_TYPE *)ASN1_NULL_new(); | |
230 | if (asn1null == NULL) | |
231 | return 0; | |
232 | if ((itav = OSSL_CMP_ITAV_create(OBJ_nid2obj(NID_id_it_implicitConfirm), | |
233 | asn1null)) == NULL) | |
234 | goto err; | |
235 | if (!ossl_cmp_hdr_generalInfo_push0_item(hdr, itav)) | |
236 | goto err; | |
237 | return 1; | |
238 | ||
239 | err: | |
240 | ASN1_TYPE_free(asn1null); | |
241 | OSSL_CMP_ITAV_free(itav); | |
242 | return 0; | |
243 | } | |
244 | ||
245 | /* return 1 if implicitConfirm in the generalInfo field of the header is set */ | |
62dcd2aa | 246 | int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr) |
4dde554c DDO |
247 | { |
248 | int itavCount; | |
249 | int i; | |
250 | OSSL_CMP_ITAV *itav; | |
251 | ||
252 | if (!ossl_assert(hdr != NULL)) | |
253 | return 0; | |
254 | ||
255 | itavCount = sk_OSSL_CMP_ITAV_num(hdr->generalInfo); | |
256 | for (i = 0; i < itavCount; i++) { | |
257 | itav = sk_OSSL_CMP_ITAV_value(hdr->generalInfo, i); | |
258 | if (itav != NULL | |
259 | && OBJ_obj2nid(itav->infoType) == NID_id_it_implicitConfirm) | |
260 | return 1; | |
261 | } | |
262 | ||
263 | return 0; | |
264 | } | |
265 | ||
266 | /* fill in all fields of the hdr according to the info given in ctx */ | |
267 | int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr) | |
268 | { | |
8cc86b81 DDO |
269 | const X509_NAME *sender; |
270 | const X509_NAME *rcp = NULL; | |
4dde554c DDO |
271 | |
272 | if (!ossl_assert(ctx != NULL && hdr != NULL)) | |
273 | return 0; | |
274 | ||
275 | /* set the CMP version */ | |
276 | if (!ossl_cmp_hdr_set_pvno(hdr, OSSL_CMP_PVNO)) | |
277 | return 0; | |
278 | ||
4dde554c DDO |
279 | /* |
280 | * The sender name is copied from the subject of the client cert, if any, | |
62dcd2aa | 281 | * or else from the subject name provided for certification requests. |
4dde554c | 282 | */ |
cfca56df DDO |
283 | sender = ctx->clCert != NULL ? |
284 | X509_get_subject_name(ctx->clCert) : ctx->subjectName; | |
4dde554c DDO |
285 | if (!ossl_cmp_hdr_set1_sender(hdr, sender)) |
286 | return 0; | |
287 | ||
288 | /* determine recipient entry in PKIHeader */ | |
289 | if (ctx->srvCert != NULL) { | |
290 | rcp = X509_get_subject_name(ctx->srvCert); | |
291 | /* set also as expected_sender of responses unless set explicitly */ | |
292 | if (ctx->expected_sender == NULL && rcp != NULL | |
293 | && !OSSL_CMP_CTX_set1_expected_sender(ctx, rcp)) | |
294 | return 0; | |
295 | } else if (ctx->recipient != NULL) { | |
296 | rcp = ctx->recipient; | |
297 | } else if (ctx->issuer != NULL) { | |
298 | rcp = ctx->issuer; | |
299 | } else if (ctx->oldCert != NULL) { | |
300 | rcp = X509_get_issuer_name(ctx->oldCert); | |
301 | } else if (ctx->clCert != NULL) { | |
302 | rcp = X509_get_issuer_name(ctx->clCert); | |
303 | } | |
304 | if (!ossl_cmp_hdr_set1_recipient(hdr, rcp)) | |
305 | return 0; | |
306 | ||
307 | /* set current time as message time */ | |
308 | if (!ossl_cmp_hdr_update_messageTime(hdr)) | |
309 | return 0; | |
310 | ||
311 | if (ctx->recipNonce != NULL | |
312 | && !ossl_cmp_asn1_octet_string_set1(&hdr->recipNonce, | |
313 | ctx->recipNonce)) | |
314 | return 0; | |
315 | ||
316 | /* | |
317 | * set ctx->transactionID in CMP header | |
318 | * if ctx->transactionID is NULL, a random one is created with 128 bit | |
319 | * according to section 5.1.1: | |
320 | * | |
321 | * It is RECOMMENDED that the clients fill the transactionID field with | |
322 | * 128 bits of (pseudo-) random data for the start of a transaction to | |
323 | * reduce the probability of having the transactionID in use at the server. | |
324 | */ | |
325 | if (ctx->transactionID == NULL | |
326 | && !set1_aostr_else_random(&ctx->transactionID, NULL, | |
327 | OSSL_CMP_TRANSACTIONID_LENGTH)) | |
328 | return 0; | |
329 | if (!ossl_cmp_asn1_octet_string_set1(&hdr->transactionID, | |
330 | ctx->transactionID)) | |
331 | return 0; | |
332 | ||
333 | /*- | |
334 | * set random senderNonce | |
335 | * according to section 5.1.1: | |
336 | * | |
337 | * senderNonce present | |
338 | * -- 128 (pseudo-)random bits | |
339 | * The senderNonce and recipNonce fields protect the PKIMessage against | |
340 | * replay attacks. The senderNonce will typically be 128 bits of | |
341 | * (pseudo-) random data generated by the sender, whereas the recipNonce | |
342 | * is copied from the senderNonce of the previous message in the | |
343 | * transaction. | |
344 | */ | |
345 | if (!set1_aostr_else_random(&hdr->senderNonce, NULL, | |
346 | OSSL_CMP_SENDERNONCE_LENGTH)) | |
347 | return 0; | |
348 | ||
349 | /* store senderNonce - for cmp with recipNonce in next outgoing msg */ | |
350 | if (!OSSL_CMP_CTX_set1_senderNonce(ctx, hdr->senderNonce)) | |
351 | return 0; | |
352 | ||
353 | /*- | |
354 | * freeText [7] PKIFreeText OPTIONAL, | |
355 | * -- this may be used to indicate context-specific instructions | |
356 | * -- (this field is intended for human consumption) | |
357 | */ | |
358 | if (ctx->freeText != NULL | |
359 | && !ossl_cmp_hdr_push1_freeText(hdr, ctx->freeText)) | |
360 | return 0; | |
361 | ||
362 | return 1; | |
363 | } |