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