- split up in libstrong, charon, stroke, testing done
[strongswan.git] / Source / lib / crypto / certificate.c
1 /**
2 * @file certificate.c
3 *
4 * @brief Implementation of certificate_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <gmp.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include "certificate.h"
28
29 #include <daemon.h>
30 #include <asn1/der_decoder.h>
31
32
33 typedef struct private_certificate_t private_certificate_t;
34
35 /**
36 * Private data of a certificate_t object.
37 */
38 struct private_certificate_t {
39 /**
40 * Public interface for this signer.
41 */
42 certificate_t public;
43
44 u_int version;
45
46 u_int serial;
47
48 chunk_t sign_alg;
49
50 time_t not_before;
51
52 time_t not_after;
53
54 chunk_t pubkey;
55
56 chunk_t pubkey_alg;
57
58 bool has_issuer_uid;
59 chunk_t issuer_uid;
60
61 bool has_subject_uid;
62 chunk_t subject_uid;
63
64 chunk_t tbs_cert;
65 chunk_t signature;
66
67 rsa_public_key_t *public_key;
68 };
69
70 #define OSET(x) offsetof(private_certificate_t, x)
71
72 /**
73 * Rules for de-/encoding of a certificate from/in ASN1
74 */
75 static asn1_rule_t certificate_rules[] = {
76 {ASN1_SEQUENCE, 0, 0, 0 }, /* certificate */
77 { ASN1_SEQUENCE, ASN1_RAW, OSET(tbs_cert), 0 }, /* tbsCertificate */
78 { ASN1_TAG_E_0, ASN1_DEFAULT, OSET(version), 0 }, /* EXPLICIT */
79 { ASN1_INTEGER, ASN1_DEFAULT, OSET(version), 0 }, /* version DEFAULT v1(0) */
80 { ASN1_INTEGER, 0, OSET(serial), 0 }, /* serialNumber */
81 { ASN1_SEQUENCE, 0, 0, 0 }, /* signature */
82 { ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
83 { ASN1_NULL, 0, 0, 0 }, /* parameters */
84 { ASN1_END, 0, 0, 0 }, /* signature */
85 { ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* issuer */
86 // { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
87 // { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
88 // { ASN1_OID, 0, 0, 0 }, /* AttributeType */
89 // { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
90 // { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
91 // { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
92 { ASN1_END, 0, 0, 0 }, /* issuer */
93 { ASN1_SEQUENCE, 0, 0, 0 }, /* validity */
94 { ASN1_CHOICE, 0, 0, 0 }, /* notBefore */
95 { ASN1_UTCTIME, 0, OSET(not_before), 0 }, /* utcTime */
96 { ASN1_GENERALIZEDTIME, 0, OSET(not_before), 0 }, /* generalTime */
97 { ASN1_END, 0, 0, 0 }, /* notBefore */
98 { ASN1_CHOICE, 0, 0, 0 }, /* notAfter */
99 { ASN1_UTCTIME, 0, OSET(not_after), 0 }, /* utcTime */
100 { ASN1_GENERALIZEDTIME, 0, OSET(not_after), 0 }, /* generalTime */
101 { ASN1_END, 0, 0, 0 }, /* notAfter */
102 { ASN1_END, 0, 0, 0 }, /* validity */
103 { ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* subject */
104 // { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
105 // { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
106 // { ASN1_OID, 0, 0, 0 }, /* AttributeType */
107 // { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
108 // { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
109 // { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
110 { ASN1_END, 0, 0, 0 }, /* subject */
111 { ASN1_SEQUENCE, 0, 0, 0 }, /* subjectPublicKeyInfo */
112 { ASN1_SEQUENCE, 0, 0, 0 }, /* algorithm */
113 { ASN1_OID, 0, OSET(pubkey_alg), 0 }, /* algorithm-oid */
114 { ASN1_NULL, 0, 0, 0 }, /* parameters */
115 { ASN1_END, 0, 0, 0 }, /* algorithm */
116 { ASN1_BITSTRING, 0, OSET(pubkey), 0 }, /* subjectPublicKey */
117 { ASN1_END, 0, 0, 0 }, /* subjectPublicKeyInfo */
118 { ASN1_TAG_I_1, ASN1_OPTIONAL, 0, OSET(has_issuer_uid)}, /* IMPLICIT */
119 { ASN1_BITSTRING, ASN1_OPTIONAL, OSET(issuer_uid), 0 }, /* issuerUniqueID OPTIONAL */
120 { ASN1_TAG_I_2, ASN1_OPTIONAL, 0, OSET(has_subject_uid)},/* IMPLICIT */
121 { ASN1_BITSTRING, ASN1_OPTIONAL, OSET(subject_uid), 0 }, /* subjectUniqueID OPTIONAL */
122 { ASN1_TAG_E_3, ASN1_OPTIONAL, 0, 0 }, /* EXPLICIT */
123 { ASN1_SEQUENCE, ASN1_OF|ASN1_OPTIONAL, 0, 0 }, /* extensions OPTIONAL */
124 // { ASN1_SEQUENCE, 0, 0, 0, }, /* extension */
125 // { ASN1_OID, 0, 0, 0 }, /* extnID */
126 // { ASN1_BOOLEAN, ASN1_DEFAULT, 0, FALSE }, /* critical */
127 // { ASN1_OCTETSTRING, 0, 0, 0, }, /* extnValue */
128 // { ASN1_END, 0, 0, 0, }, /* extension */
129 { ASN1_END, 0, 0, 0, }, /* extensions */
130 { ASN1_END, 0, 0, 0 }, /* tbsCertificate */
131 { ASN1_SEQUENCE, 0, 0, 0 }, /* signatureAlgorithm */
132 { ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
133 { ASN1_NULL, 0, 0, 0 }, /* parameters */
134 { ASN1_END, 0, 0, 0 }, /* signatureAlgorithm */
135 { ASN1_BITSTRING, 0, OSET(signature), 0 }, /* signatureValue */
136 {ASN1_END, 0, 0, 0 }, /* certificate */
137 };
138
139 /**
140 * Implementation of certificate.get_public_key.
141 */
142 static rsa_public_key_t *get_public_key(private_certificate_t *this)
143 {
144 return this->public_key->clone(this->public_key);
145 }
146
147 /**
148 * Implementation of certificate.destroy.
149 */
150 static void destroy(private_certificate_t *this)
151 {
152 this->public_key->destroy(this->public_key);
153 free(this->pubkey.ptr);
154 free(this->signature.ptr);
155 free(this->tbs_cert.ptr);
156 free(this);
157 }
158
159 /*
160 * Described in header.
161 */
162 certificate_t *certificate_create_from_chunk(chunk_t chunk)
163 {
164 private_certificate_t *this = malloc_thing(private_certificate_t);
165 der_decoder_t *dd;
166
167 /* public functions */
168 this->public.get_public_key = (rsa_public_key_t *(*) (certificate_t*))get_public_key;
169 this->public.destroy = (void (*) (certificate_t*))destroy;
170
171 /* initialize */
172 this->pubkey = CHUNK_INITIALIZER;
173 this->signature = CHUNK_INITIALIZER;
174 this->tbs_cert = CHUNK_INITIALIZER;
175
176 dd = der_decoder_create(certificate_rules);
177
178 if (dd->decode(dd, chunk, this) != SUCCESS)
179 {
180 free(this);
181 dd->destroy(dd);
182 return NULL;
183 }
184 dd->destroy(dd);
185
186 this->public_key = rsa_public_key_create_from_chunk(this->pubkey);
187 if (this->public_key == NULL)
188 {
189 free(this->pubkey.ptr);
190 free(this);
191 return NULL;
192 }
193
194 return &this->public;
195 }
196
197 /*
198 * Described in header.
199 */
200 certificate_t *certificate_create_from_file(char *filename)
201 {
202 struct stat stb;
203 FILE *file;
204 char *buffer;
205 chunk_t chunk;
206
207 if (stat(filename, &stb) == -1)
208 {
209 return NULL;
210 }
211
212 buffer = alloca(stb.st_size);
213
214 file = fopen(filename, "r");
215 if (file == NULL)
216 {
217 return NULL;
218 }
219
220 if (fread(buffer, stb.st_size, 1, file) == -1)
221 {
222 fclose(file);
223 return NULL;
224 }
225 fclose(file);
226
227 chunk.ptr = buffer;
228 chunk.len = stb.st_size;
229
230 return certificate_create_from_chunk(chunk);
231 }