../svn-commit.tmp
[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 <utils/allocator.h>
31 #include <asn1/der_decoder.h>
32
33
34 typedef struct private_certificate_t private_certificate_t;
35
36 /**
37 * Private data of a certificate_t object.
38 */
39 struct private_certificate_t {
40 /**
41 * Public interface for this signer.
42 */
43 certificate_t public;
44
45 u_int version;
46
47 u_int serial;
48
49 chunk_t sign_alg;
50
51 time_t not_before;
52
53 time_t not_after;
54
55 chunk_t pubkey;
56
57 chunk_t pubkey_alg;
58
59 bool has_issuer_uid;
60 chunk_t issuer_uid;
61
62 bool has_subject_uid;
63 chunk_t subject_uid;
64
65 chunk_t tbs_cert;
66 chunk_t signature;
67
68 rsa_public_key_t *public_key;
69 };
70
71 #define OSET(x) offsetof(private_certificate_t, x)
72
73 /**
74 * Rules for de-/encoding of a certificate from/in ASN1
75 */
76 static asn1_rule_t certificate_rules[] = {
77 {ASN1_SEQUENCE, 0, 0, 0 }, /* certificate */
78 { ASN1_SEQUENCE, ASN1_RAW, OSET(tbs_cert), 0 }, /* tbsCertificate */
79 { ASN1_TAG_E_0, ASN1_DEFAULT, OSET(version), 0 }, /* EXPLICIT */
80 { ASN1_INTEGER, ASN1_DEFAULT, OSET(version), 0 }, /* version DEFAULT v1(0) */
81 { ASN1_INTEGER, 0, OSET(serial), 0 }, /* serialNumber */
82 { ASN1_SEQUENCE, 0, 0, 0 }, /* signature */
83 { ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
84 { ASN1_NULL, 0, 0, 0 }, /* parameters */
85 { ASN1_END, 0, 0, 0 }, /* signature */
86 { ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* issuer */
87 // { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
88 // { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
89 // { ASN1_OID, 0, 0, 0 }, /* AttributeType */
90 // { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
91 // { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
92 // { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
93 { ASN1_END, 0, 0, 0 }, /* issuer */
94 { ASN1_SEQUENCE, 0, 0, 0 }, /* validity */
95 { ASN1_CHOICE, 0, 0, 0 }, /* notBefore */
96 { ASN1_UTCTIME, 0, OSET(not_before), 0 }, /* utcTime */
97 { ASN1_GENERALIZEDTIME, 0, OSET(not_before), 0 }, /* generalTime */
98 { ASN1_END, 0, 0, 0 }, /* notBefore */
99 { ASN1_CHOICE, 0, 0, 0 }, /* notAfter */
100 { ASN1_UTCTIME, 0, OSET(not_after), 0 }, /* utcTime */
101 { ASN1_GENERALIZEDTIME, 0, OSET(not_after), 0 }, /* generalTime */
102 { ASN1_END, 0, 0, 0 }, /* notAfter */
103 { ASN1_END, 0, 0, 0 }, /* validity */
104 { ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* subject */
105 // { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
106 // { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
107 // { ASN1_OID, 0, 0, 0 }, /* AttributeType */
108 // { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
109 // { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
110 // { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
111 { ASN1_END, 0, 0, 0 }, /* subject */
112 { ASN1_SEQUENCE, 0, 0, 0 }, /* subjectPublicKeyInfo */
113 { ASN1_SEQUENCE, 0, 0, 0 }, /* algorithm */
114 { ASN1_OID, 0, OSET(pubkey_alg), 0 }, /* algorithm-oid */
115 { ASN1_NULL, 0, 0, 0 }, /* parameters */
116 { ASN1_END, 0, 0, 0 }, /* algorithm */
117 { ASN1_BITSTRING, 0, OSET(pubkey), 0 }, /* subjectPublicKey */
118 { ASN1_END, 0, 0, 0 }, /* subjectPublicKeyInfo */
119 { ASN1_TAG_I_1, ASN1_OPTIONAL, 0, OSET(has_issuer_uid)}, /* IMPLICIT */
120 { ASN1_BITSTRING, ASN1_OPTIONAL, OSET(issuer_uid), 0 }, /* issuerUniqueID OPTIONAL */
121 { ASN1_TAG_I_2, ASN1_OPTIONAL, 0, OSET(has_subject_uid)},/* IMPLICIT */
122 { ASN1_BITSTRING, ASN1_OPTIONAL, OSET(subject_uid), 0 }, /* subjectUniqueID OPTIONAL */
123 { ASN1_TAG_E_3, ASN1_OPTIONAL, 0, 0 }, /* EXPLICIT */
124 { ASN1_SEQUENCE, ASN1_OF|ASN1_OPTIONAL, 0, 0 }, /* extensions OPTIONAL */
125 // { ASN1_SEQUENCE, 0, 0, 0, }, /* extension */
126 // { ASN1_OID, 0, 0, 0 }, /* extnID */
127 // { ASN1_BOOLEAN, ASN1_DEFAULT, 0, FALSE }, /* critical */
128 // { ASN1_OCTETSTRING, 0, 0, 0, }, /* extnValue */
129 // { ASN1_END, 0, 0, 0, }, /* extension */
130 { ASN1_END, 0, 0, 0, }, /* extensions */
131 { ASN1_END, 0, 0, 0 }, /* tbsCertificate */
132 { ASN1_SEQUENCE, 0, 0, 0 }, /* signatureAlgorithm */
133 { ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
134 { ASN1_NULL, 0, 0, 0 }, /* parameters */
135 { ASN1_END, 0, 0, 0 }, /* signatureAlgorithm */
136 { ASN1_BITSTRING, 0, OSET(signature), 0 }, /* signatureValue */
137 {ASN1_END, 0, 0, 0 }, /* certificate */
138 };
139
140 /**
141 * Implementation of certificate.get_public_key.
142 */
143 static rsa_public_key_t *get_public_key(private_certificate_t *this)
144 {
145 return this->public_key->clone(this->public_key);
146 }
147
148 /**
149 * Implementation of certificate.destroy.
150 */
151 static void destroy(private_certificate_t *this)
152 {
153 this->public_key->destroy(this->public_key);
154 allocator_free(this->pubkey.ptr);
155 allocator_free(this->signature.ptr);
156 allocator_free(this->tbs_cert.ptr);
157 allocator_free(this);
158 }
159
160 /*
161 * Described in header.
162 */
163 certificate_t *certificate_create_from_chunk(chunk_t chunk)
164 {
165 private_certificate_t *this = allocator_alloc_thing(private_certificate_t);
166 der_decoder_t *dd;
167
168 /* public functions */
169 this->public.get_public_key = (rsa_public_key_t *(*) (certificate_t*))get_public_key;
170 this->public.destroy = (void (*) (certificate_t*))destroy;
171
172 /* initialize */
173 this->pubkey = CHUNK_INITIALIZER;
174 this->signature = CHUNK_INITIALIZER;
175 this->tbs_cert = CHUNK_INITIALIZER;
176
177 dd = der_decoder_create(certificate_rules);
178
179 if (dd->decode(dd, chunk, this) != SUCCESS)
180 {
181 allocator_free(this);
182 dd->destroy(dd);
183 return NULL;
184 }
185 dd->destroy(dd);
186
187 this->public_key = rsa_public_key_create_from_chunk(this->pubkey);
188 if (this->public_key == NULL)
189 {
190 allocator_free(this->pubkey.ptr);
191 allocator_free(this);
192 return NULL;
193 }
194
195 return &this->public;
196 }
197
198 /*
199 * Described in header.
200 */
201 certificate_t *certificate_create_from_file(char *filename)
202 {
203 struct stat stb;
204 FILE *file;
205 char *buffer;
206 chunk_t chunk;
207
208 if (stat(filename, &stb) == -1)
209 {
210 return NULL;
211 }
212
213 buffer = alloca(stb.st_size);
214
215 file = fopen(filename, "r");
216 if (file == NULL)
217 {
218 return NULL;
219 }
220
221 if (fread(buffer, stb.st_size, 1, file) == -1)
222 {
223 return NULL;
224 }
225
226 chunk.ptr = buffer;
227 chunk.len = stb.st_size;
228
229 return certificate_create_from_chunk(chunk);
230 }