2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2010 Martin Willi
4 * Copyright (C) 2010 revosec AG
5 * Copyright (C) 2005 Jan Hutter
6 * Hochschule fuer Technik Rapperswil
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 #include "cert_payload.h"
26 ENUM(cert_encoding_names
, ENC_PKCS7_WRAPPED_X509
, ENC_OCSP_CONTENT
,
27 "ENC_PKCS7_WRAPPED_X509",
31 "ENC_X509_KEY_EXCHANGE",
32 "ENC_KERBEROS_TOKENS",
38 "ENC_X509_HASH_AND_URL",
39 "ENC_X509_HASH_AND_URL_BUNDLE",
43 typedef struct private_cert_payload_t private_cert_payload_t
;
46 * Private data of an cert_payload_t object.
48 struct private_cert_payload_t
{
51 * Public cert_payload_t interface.
53 cert_payload_t
public;
58 u_int8_t next_payload
;
71 * Length of this payload.
73 u_int16_t payload_length
;
76 * Encoding of the CERT Data.
81 * The contained cert data value.
86 * TRUE if the "Hash and URL" data is invalid
88 bool invalid_hash_and_url
;
92 * Encoding rules to parse or generate a CERT payload
94 * The defined offsets are the positions in a object of type
95 * private_cert_payload_t.
98 static encoding_rule_t encodings
[] = {
99 /* 1 Byte next payload type, stored in the field next_payload */
100 { U_INT_8
, offsetof(private_cert_payload_t
, next_payload
) },
101 /* the critical bit */
102 { FLAG
, offsetof(private_cert_payload_t
, critical
) },
103 /* 7 Bit reserved bits, nowhere stored */
104 { RESERVED_BIT
, offsetof(private_cert_payload_t
, reserved
[0]) },
105 { RESERVED_BIT
, offsetof(private_cert_payload_t
, reserved
[1]) },
106 { RESERVED_BIT
, offsetof(private_cert_payload_t
, reserved
[2]) },
107 { RESERVED_BIT
, offsetof(private_cert_payload_t
, reserved
[3]) },
108 { RESERVED_BIT
, offsetof(private_cert_payload_t
, reserved
[4]) },
109 { RESERVED_BIT
, offsetof(private_cert_payload_t
, reserved
[5]) },
110 { RESERVED_BIT
, offsetof(private_cert_payload_t
, reserved
[6]) },
111 /* Length of the whole payload*/
112 { PAYLOAD_LENGTH
, offsetof(private_cert_payload_t
, payload_length
)},
113 /* 1 Byte CERT type*/
114 { U_INT_8
, offsetof(private_cert_payload_t
, encoding
) },
115 /* some cert data bytes, length is defined in PAYLOAD_LENGTH */
116 { CERT_DATA
, offsetof(private_cert_payload_t
, data
) }
121 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
122 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123 ! Next Payload !C! RESERVED ! Payload Length !
124 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132 METHOD(payload_t
, verify
, status_t
,
133 private_cert_payload_t
*this)
135 if (this->encoding
== ENC_X509_HASH_AND_URL
||
136 this->encoding
== ENC_X509_HASH_AND_URL_BUNDLE
)
140 /* coarse verification of "Hash and URL" encoded certificates */
141 if (this->data
.len
<= 20)
143 DBG1(DBG_ENC
, "invalid payload length for hash-and-url (%d), ignore",
145 this->invalid_hash_and_url
= TRUE
;
148 for (i
= 20; i
< this->data
.len
; ++i
)
150 if (this->data
.ptr
[i
] == '\0')
152 /* null terminated, fine */
155 else if (!isprint(this->data
.ptr
[i
]))
157 DBG1(DBG_ENC
, "non printable characters in url of hash-and-url"
158 " encoded certificate payload, ignore");
159 this->invalid_hash_and_url
= TRUE
;
163 /* URL is not null terminated, correct that */
164 this->data
= chunk_cat("mc", this->data
, chunk_from_chars(0));
169 METHOD(payload_t
, get_encoding_rules
, int,
170 private_cert_payload_t
*this, encoding_rule_t
**rules
)
173 return countof(encodings
);
176 METHOD(payload_t
, get_type
, payload_type_t
,
177 private_cert_payload_t
*this)
182 METHOD(payload_t
, get_next_type
, payload_type_t
,
183 private_cert_payload_t
*this)
185 return this->next_payload
;
188 METHOD(payload_t
, set_next_type
, void,
189 private_cert_payload_t
*this, payload_type_t type
)
191 this->next_payload
= type
;
194 METHOD(payload_t
, get_length
, size_t,
195 private_cert_payload_t
*this)
197 return this->payload_length
;
200 METHOD(cert_payload_t
, get_cert_encoding
, cert_encoding_t
,
201 private_cert_payload_t
*this)
203 return this->encoding
;
206 METHOD(cert_payload_t
, get_cert
, certificate_t
*,
207 private_cert_payload_t
*this)
211 switch (this->encoding
)
213 case ENC_X509_SIGNATURE
:
217 type
= CERT_X509_CRL
;
222 return lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, type
,
223 BUILD_BLOB_ASN1_DER
, this->data
, BUILD_END
);
226 METHOD(cert_payload_t
, get_hash
, chunk_t
,
227 private_cert_payload_t
*this)
229 chunk_t hash
= chunk_empty
;
231 if ((this->encoding
!= ENC_X509_HASH_AND_URL
&&
232 this->encoding
!= ENC_X509_HASH_AND_URL_BUNDLE
) ||
233 this->invalid_hash_and_url
)
237 hash
.ptr
= this->data
.ptr
;
242 METHOD(cert_payload_t
, get_url
, char*,
243 private_cert_payload_t
*this)
245 if ((this->encoding
!= ENC_X509_HASH_AND_URL
&&
246 this->encoding
!= ENC_X509_HASH_AND_URL_BUNDLE
) ||
247 this->invalid_hash_and_url
)
251 return (char*)this->data
.ptr
+ 20;
254 METHOD2(payload_t
, cert_payload_t
, destroy
, void,
255 private_cert_payload_t
*this)
257 free(this->data
.ptr
);
262 * Described in header
264 cert_payload_t
*cert_payload_create()
266 private_cert_payload_t
*this;
270 .payload_interface
= {
272 .get_encoding_rules
= _get_encoding_rules
,
273 .get_length
= _get_length
,
274 .get_next_type
= _get_next_type
,
275 .set_next_type
= _set_next_type
,
276 .get_type
= _get_type
,
279 .get_cert
= _get_cert
,
280 .get_cert_encoding
= _get_cert_encoding
,
281 .get_hash
= _get_hash
,
285 .next_payload
= NO_PAYLOAD
,
286 .payload_length
= CERT_PAYLOAD_HEADER_LENGTH
,
288 return &this->public;
292 * Described in header
294 cert_payload_t
*cert_payload_create_from_cert(certificate_t
*cert
)
296 private_cert_payload_t
*this = (private_cert_payload_t
*)cert_payload_create();
298 switch (cert
->get_type(cert
))
301 this->encoding
= ENC_X509_SIGNATURE
;
304 DBG1(DBG_ENC
, "embedding %N certificate in payload failed",
305 certificate_type_names
, cert
->get_type(cert
));
309 if (!cert
->get_encoding(cert
, CERT_ASN1_DER
, &this->data
))
311 DBG1(DBG_ENC
, "encoding certificate for cert payload failed");
315 this->payload_length
= CERT_PAYLOAD_HEADER_LENGTH
+ this->data
.len
;
316 return &this->public;
320 * Described in header
322 cert_payload_t
*cert_payload_create_from_hash_and_url(chunk_t hash
, char *url
)
324 private_cert_payload_t
*this = (private_cert_payload_t
*)cert_payload_create();
326 this->encoding
= ENC_X509_HASH_AND_URL
;
327 this->data
= chunk_cat("cc", hash
, chunk_create(url
, strlen(url
)));
328 this->payload_length
= CERT_PAYLOAD_HEADER_LENGTH
+ this->data
.len
;
329 return &this->public;
333 * Described in header
335 cert_payload_t
*cert_payload_create_custom(cert_encoding_t type
, chunk_t data
)
337 private_cert_payload_t
*this = (private_cert_payload_t
*)cert_payload_create();
339 this->encoding
= type
;
341 this->payload_length
= CERT_PAYLOAD_HEADER_LENGTH
+ this->data
.len
;
342 return &this->public;