openssl: Make some utilities take const BIGNUM pointers
[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 /* these were added with 1.1.0 when ASN1_OBJECT was made opaque */
26 #if OPENSSL_VERSION_NUMBER < 0x10100000L
27 #define OBJ_get0_data(o) ((o)->data)
28 #define OBJ_length(o) ((o)->length)
29 #endif
30
31 /**
32 * Described in header.
33 */
34 bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash)
35 {
36 EVP_MD_CTX *ctx;
37 bool ret = FALSE;
38 const EVP_MD *hasher = EVP_get_digestbynid(hash_type);
39 if (!hasher)
40 {
41 return FALSE;
42 }
43
44 ctx = EVP_MD_CTX_create();
45 if (!ctx)
46 {
47 goto error;
48 }
49
50 if (!EVP_DigestInit_ex(ctx, hasher, NULL))
51 {
52 goto error;
53 }
54
55 if (!EVP_DigestUpdate(ctx, data.ptr, data.len))
56 {
57 goto error;
58 }
59
60 *hash = chunk_alloc(EVP_MD_size(hasher));
61 if (!EVP_DigestFinal_ex(ctx, hash->ptr, NULL))
62 {
63 chunk_free(hash);
64 goto error;
65 }
66
67 ret = TRUE;
68 error:
69 if (ctx)
70 {
71 EVP_MD_CTX_destroy(ctx);
72 }
73 return ret;
74 }
75
76 /**
77 * Described in header.
78 */
79 bool openssl_bn_cat(const int len, const BIGNUM *a, const BIGNUM *b,
80 chunk_t *chunk)
81 {
82 int offset;
83
84 chunk->len = len + (b ? len : 0);
85 chunk->ptr = malloc(chunk->len);
86 memset(chunk->ptr, 0, chunk->len);
87
88 /* convert a */
89 offset = len - BN_num_bytes(a);
90 if (!BN_bn2bin(a, chunk->ptr + offset))
91 {
92 goto error;
93 }
94
95 /* optionally convert and concatenate b */
96 if (b)
97 {
98 offset = len - BN_num_bytes(b);
99 if (!BN_bn2bin(b, chunk->ptr + len + offset))
100 {
101 goto error;
102 }
103 }
104
105 return TRUE;
106 error:
107 chunk_free(chunk);
108 return FALSE;
109 }
110
111 /**
112 * Described in header.
113 */
114 bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b)
115 {
116 int len;
117
118 if ((chunk.len % 2) != 0)
119 {
120 return FALSE;
121 }
122
123 len = chunk.len / 2;
124
125 if (!BN_bin2bn(chunk.ptr, len, a) ||
126 !BN_bin2bn(chunk.ptr + len, len, b))
127 {
128 return FALSE;
129 }
130
131 return TRUE;
132 }
133
134 /**
135 * Described in header.
136 */
137 bool openssl_bn2chunk(const BIGNUM *bn, chunk_t *chunk)
138 {
139 *chunk = chunk_alloc(BN_num_bytes(bn));
140 if (BN_bn2bin(bn, chunk->ptr) == chunk->len)
141 {
142 if (chunk->len && chunk->ptr[0] & 0x80)
143 { /* if MSB is set, prepend a zero to make it non-negative */
144 *chunk = chunk_cat("cm", chunk_from_chars(0x00), *chunk);
145 }
146 return TRUE;
147 }
148 chunk_free(chunk);
149 return FALSE;
150 }
151
152 /**
153 * Described in header.
154 */
155 chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1)
156 {
157 if (asn1)
158 {
159 return chunk_create((u_char*)OBJ_get0_data(asn1), OBJ_length(asn1));
160 }
161 return chunk_empty;
162 }
163
164 /**
165 * Described in header.
166 */
167 chunk_t openssl_asn1_str2chunk(ASN1_STRING *asn1)
168 {
169 if (asn1)
170 {
171 return chunk_create(ASN1_STRING_data(asn1), ASN1_STRING_length(asn1));
172 }
173 return chunk_empty;
174 }
175
176 /**
177 * Convert a X509 name to a ID_DER_ASN1_DN identification_t
178 */
179 identification_t *openssl_x509_name2id(X509_NAME *name)
180 {
181 if (name)
182 {
183 identification_t *id;
184 chunk_t chunk;
185
186 chunk = openssl_i2chunk(X509_NAME, name);
187 if (chunk.len)
188 {
189 id = identification_create_from_encoding(ID_DER_ASN1_DN, chunk);
190 free(chunk.ptr);
191 return id;
192 }
193 }
194 return NULL;
195 }
196
197 /**
198 * We can't include <asn1/asn1.h>, as the ASN1_ definitions would clash
199 * with OpenSSL. Redeclare what we need.
200 */
201 int asn1_known_oid(chunk_t);
202 time_t asn1_to_time(chunk_t *,int);
203
204 /**
205 * Described in header.
206 */
207 int openssl_asn1_known_oid(ASN1_OBJECT *obj)
208 {
209 return asn1_known_oid(openssl_asn1_obj2chunk(obj));
210 }
211
212 /**
213 * Described in header.
214 */
215 time_t openssl_asn1_to_time(ASN1_TIME *time)
216 {
217 chunk_t chunk;
218
219 if (time)
220 {
221 chunk = openssl_asn1_str2chunk(time);
222 switch (time->type)
223 {
224 case V_ASN1_UTCTIME:
225 case V_ASN1_GENERALIZEDTIME:
226 return asn1_to_time(&chunk, time->type);
227 default:
228 break;
229 }
230 }
231 DBG1(DBG_LIB, "invalid ASN1 time");
232 return 0;
233 }