openssl: Explicitly include openssl/bn.h
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_util.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Copyright (C) 2008 Tobias Brunner
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "openssl_util.h"
18
19 #include <utils/debug.h>
20
21 #include <openssl/bn.h>
22 #include <openssl/evp.h>
23 #include <openssl/x509.h>
24
25 /**
26 * Described in header.
27 */
28 bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash)
29 {
30 EVP_MD_CTX *ctx;
31 bool ret = FALSE;
32 const EVP_MD *hasher = EVP_get_digestbynid(hash_type);
33 if (!hasher)
34 {
35 return FALSE;
36 }
37
38 ctx = EVP_MD_CTX_create();
39 if (!ctx)
40 {
41 goto error;
42 }
43
44 if (!EVP_DigestInit_ex(ctx, hasher, NULL))
45 {
46 goto error;
47 }
48
49 if (!EVP_DigestUpdate(ctx, data.ptr, data.len))
50 {
51 goto error;
52 }
53
54 *hash = chunk_alloc(hasher->md_size);
55 if (!EVP_DigestFinal_ex(ctx, hash->ptr, NULL))
56 {
57 chunk_free(hash);
58 goto error;
59 }
60
61 ret = TRUE;
62 error:
63 if (ctx)
64 {
65 EVP_MD_CTX_destroy(ctx);
66 }
67 return ret;
68 }
69
70 /**
71 * Described in header.
72 */
73 bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk)
74 {
75 int offset;
76
77 chunk->len = len + (b ? len : 0);
78 chunk->ptr = malloc(chunk->len);
79 memset(chunk->ptr, 0, chunk->len);
80
81 /* convert a */
82 offset = len - BN_num_bytes(a);
83 if (!BN_bn2bin(a, chunk->ptr + offset))
84 {
85 goto error;
86 }
87
88 /* optionally convert and concatenate b */
89 if (b)
90 {
91 offset = len - BN_num_bytes(b);
92 if (!BN_bn2bin(b, chunk->ptr + len + offset))
93 {
94 goto error;
95 }
96 }
97
98 return TRUE;
99 error:
100 chunk_free(chunk);
101 return FALSE;
102 }
103
104 /**
105 * Described in header.
106 */
107 bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b)
108 {
109 int len;
110
111 if ((chunk.len % 2) != 0)
112 {
113 return FALSE;
114 }
115
116 len = chunk.len / 2;
117
118 if (!BN_bin2bn(chunk.ptr, len, a) ||
119 !BN_bin2bn(chunk.ptr + len, len, b))
120 {
121 return FALSE;
122 }
123
124 return TRUE;
125 }
126
127 /**
128 * Described in header.
129 */
130 bool openssl_bn2chunk(BIGNUM *bn, chunk_t *chunk)
131 {
132 *chunk = chunk_alloc(BN_num_bytes(bn));
133 if (BN_bn2bin(bn, chunk->ptr) == chunk->len)
134 {
135 if (chunk->len && chunk->ptr[0] & 0x80)
136 { /* if MSB is set, prepend a zero to make it non-negative */
137 *chunk = chunk_cat("cm", chunk_from_chars(0x00), *chunk);
138 }
139 return TRUE;
140 }
141 chunk_free(chunk);
142 return FALSE;
143 }
144
145 /**
146 * Described in header.
147 */
148 chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1)
149 {
150 if (asn1)
151 {
152 return chunk_create((u_char*)asn1->data, asn1->length);
153 }
154 return chunk_empty;
155 }
156
157 /**
158 * Described in header.
159 */
160 chunk_t openssl_asn1_str2chunk(ASN1_STRING *asn1)
161 {
162 if (asn1)
163 {
164 return chunk_create(ASN1_STRING_data(asn1), ASN1_STRING_length(asn1));
165 }
166 return chunk_empty;
167 }
168
169 /**
170 * Convert a X509 name to a ID_DER_ASN1_DN identification_t
171 */
172 identification_t *openssl_x509_name2id(X509_NAME *name)
173 {
174 if (name)
175 {
176 identification_t *id;
177 chunk_t chunk;
178
179 chunk = openssl_i2chunk(X509_NAME, name);
180 if (chunk.len)
181 {
182 id = identification_create_from_encoding(ID_DER_ASN1_DN, chunk);
183 free(chunk.ptr);
184 return id;
185 }
186 }
187 return NULL;
188 }
189
190 /**
191 * We can't include <asn1/asn1.h>, as the ASN1_ definitions would clash
192 * with OpenSSL. Redeclare what we need.
193 */
194 int asn1_known_oid(chunk_t);
195 time_t asn1_to_time(chunk_t *,int);
196
197 /**
198 * Described in header.
199 */
200 int openssl_asn1_known_oid(ASN1_OBJECT *obj)
201 {
202 return asn1_known_oid(openssl_asn1_obj2chunk(obj));
203 }
204
205 /**
206 * Described in header.
207 */
208 time_t openssl_asn1_to_time(ASN1_TIME *time)
209 {
210 chunk_t chunk;
211
212 if (time)
213 {
214 chunk = openssl_asn1_str2chunk(time);
215 switch (time->type)
216 {
217 case V_ASN1_UTCTIME:
218 case V_ASN1_GENERALIZEDTIME:
219 return asn1_to_time(&chunk, time->type);
220 default:
221 break;
222 }
223 }
224 DBG1(DBG_LIB, "invalid ASN1 time");
225 return 0;
226 }