2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 #include <crypto/hashers/hasher.h>
22 #include <encoding/payloads/cert_payload.h>
24 #include "certreq_payload.h"
26 typedef struct private_certreq_payload_t private_certreq_payload_t
;
29 * Private data of an certreq_payload_t object.
31 struct private_certreq_payload_t
{
34 * Public certreq_payload_t interface.
36 certreq_payload_t
public;
41 u_int8_t next_payload
;
54 * Length of this payload.
56 u_int16_t payload_length
;
59 * Encoding of the CERT Data.
64 * The contained certreq data value.
70 * Encoding rules to parse or generate a CERTREQ payload
72 * The defined offsets are the positions in a object of type
73 * private_certreq_payload_t.
75 static encoding_rule_t encodings
[] = {
76 /* 1 Byte next payload type, stored in the field next_payload */
77 { U_INT_8
, offsetof(private_certreq_payload_t
, next_payload
) },
78 /* the critical bit */
79 { FLAG
, offsetof(private_certreq_payload_t
, critical
) },
80 /* 7 Bit reserved bits */
81 { RESERVED_BIT
, offsetof(private_certreq_payload_t
, reserved
[0]) },
82 { RESERVED_BIT
, offsetof(private_certreq_payload_t
, reserved
[1]) },
83 { RESERVED_BIT
, offsetof(private_certreq_payload_t
, reserved
[2]) },
84 { RESERVED_BIT
, offsetof(private_certreq_payload_t
, reserved
[3]) },
85 { RESERVED_BIT
, offsetof(private_certreq_payload_t
, reserved
[4]) },
86 { RESERVED_BIT
, offsetof(private_certreq_payload_t
, reserved
[5]) },
87 { RESERVED_BIT
, offsetof(private_certreq_payload_t
, reserved
[6]) },
88 /* Length of the whole payload*/
89 { PAYLOAD_LENGTH
, offsetof(private_certreq_payload_t
, payload_length
) },
90 /* 1 Byte CERTREQ type*/
91 { U_INT_8
, offsetof(private_certreq_payload_t
, encoding
) },
92 /* some certreq data bytes, length is defined in PAYLOAD_LENGTH */
93 { CERTREQ_DATA
, offsetof(private_certreq_payload_t
, data
) }
98 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
99 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 ! Next Payload !C! RESERVED ! Payload Length !
101 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104 ~ Certification Authority ~
106 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109 METHOD(payload_t
, verify
, status_t
,
110 private_certreq_payload_t
*this)
112 if (this->encoding
== ENC_X509_SIGNATURE
)
114 if (this->data
.len
< HASH_SIZE_SHA1
||
115 this->data
.len
% HASH_SIZE_SHA1
)
117 DBG1(DBG_ENC
, "invalid X509 hash length (%d) in certreq",
125 METHOD(payload_t
, get_encoding_rules
, int,
126 private_certreq_payload_t
*this, encoding_rule_t
**rules
)
129 return countof(encodings
);
132 METHOD(payload_t
, get_type
, payload_type_t
,
133 private_certreq_payload_t
*this)
135 return CERTIFICATE_REQUEST
;
138 METHOD(payload_t
, get_next_type
, payload_type_t
,
139 private_certreq_payload_t
*this)
141 return this->next_payload
;
144 METHOD(payload_t
, set_next_type
, void,
145 private_certreq_payload_t
*this, payload_type_t type
)
147 this->next_payload
= type
;
150 METHOD(payload_t
, get_length
, size_t,
151 private_certreq_payload_t
*this)
153 return this->payload_length
;
156 METHOD(certreq_payload_t
, add_keyid
, void,
157 private_certreq_payload_t
*this, chunk_t keyid
)
159 this->data
= chunk_cat("mc", this->data
, keyid
);
160 this->payload_length
+= keyid
.len
;
163 typedef struct keyid_enumerator_t keyid_enumerator_t
;
166 * enumerator to enumerate keyids
168 struct keyid_enumerator_t
{
174 METHOD(enumerator_t
, keyid_enumerate
, bool,
175 keyid_enumerator_t
*this, chunk_t
*chunk
)
177 if (this->pos
== NULL
)
179 this->pos
= this->full
.ptr
;
183 this->pos
+= HASH_SIZE_SHA1
;
184 if (this->pos
> (this->full
.ptr
+ this->full
.len
- HASH_SIZE_SHA1
))
191 chunk
->ptr
= this->pos
;
192 chunk
->len
= HASH_SIZE_SHA1
;
198 METHOD(certreq_payload_t
, create_keyid_enumerator
, enumerator_t
*,
199 private_certreq_payload_t
*this)
201 keyid_enumerator_t
*enumerator
;
205 .enumerate
= (void*)_keyid_enumerate
,
206 .destroy
= (void*)free
,
210 return &enumerator
->public;
213 METHOD(certreq_payload_t
, get_cert_type
, certificate_type_t
,
214 private_certreq_payload_t
*this)
216 switch (this->encoding
)
218 case ENC_X509_SIGNATURE
:
225 METHOD2(payload_t
, certreq_payload_t
, destroy
, void,
226 private_certreq_payload_t
*this)
228 chunk_free(&this->data
);
233 * Described in header
235 certreq_payload_t
*certreq_payload_create()
237 private_certreq_payload_t
*this;
241 .payload_interface
= {
243 .get_encoding_rules
= _get_encoding_rules
,
244 .get_length
= _get_length
,
245 .get_next_type
= _get_next_type
,
246 .set_next_type
= _set_next_type
,
247 .get_type
= _get_type
,
250 .create_keyid_enumerator
= _create_keyid_enumerator
,
251 .get_cert_type
= _get_cert_type
,
252 .add_keyid
= _add_keyid
,
255 .next_payload
= NO_PAYLOAD
,
256 .payload_length
= CERTREQ_PAYLOAD_HEADER_LENGTH
,
258 return &this->public;
262 * Described in header
264 certreq_payload_t
*certreq_payload_create_type(certificate_type_t type
)
266 private_certreq_payload_t
*this = (private_certreq_payload_t
*)certreq_payload_create();
271 this->encoding
= ENC_X509_SIGNATURE
;
274 DBG1(DBG_ENC
, "certificate type %N not supported in requests",
275 certificate_type_names
, type
);
279 return &this->public;