1*0a6a1f1dSLionel Sambuc /* $NetBSD: rsa.c,v 1.1.1.2 2014/04/24 12:45:30 pettai Exp $ */
2ebfedea0SLionel Sambuc
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc * All rights reserved.
7ebfedea0SLionel Sambuc *
8ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc * are met:
11ebfedea0SLionel Sambuc *
12ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc *
15ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc *
19ebfedea0SLionel Sambuc * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc * may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc * without specific prior written permission.
22ebfedea0SLionel Sambuc *
23ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc * SUCH DAMAGE.
34ebfedea0SLionel Sambuc */
35ebfedea0SLionel Sambuc
36ebfedea0SLionel Sambuc #include <config.h>
37ebfedea0SLionel Sambuc
38ebfedea0SLionel Sambuc #include <stdio.h>
39ebfedea0SLionel Sambuc #include <stdlib.h>
40ebfedea0SLionel Sambuc #include <krb5/krb5-types.h>
41ebfedea0SLionel Sambuc #include <krb5/rfc2459_asn1.h>
42ebfedea0SLionel Sambuc
43ebfedea0SLionel Sambuc #include <krb5/der.h>
44ebfedea0SLionel Sambuc
45ebfedea0SLionel Sambuc #include <rsa.h>
46ebfedea0SLionel Sambuc
47ebfedea0SLionel Sambuc #include "common.h"
48ebfedea0SLionel Sambuc
49ebfedea0SLionel Sambuc #include <krb5/roken.h>
50ebfedea0SLionel Sambuc
51ebfedea0SLionel Sambuc /**
52ebfedea0SLionel Sambuc * @page page_rsa RSA - public-key cryptography
53ebfedea0SLionel Sambuc *
54ebfedea0SLionel Sambuc * RSA is named by its inventors (Ron Rivest, Adi Shamir, and Leonard
55ebfedea0SLionel Sambuc * Adleman) (published in 1977), patented expired in 21 September 2000.
56ebfedea0SLionel Sambuc *
57ebfedea0SLionel Sambuc *
58ebfedea0SLionel Sambuc * Speed for RSA in seconds
59ebfedea0SLionel Sambuc * no key blinding
60ebfedea0SLionel Sambuc * 1000 iteration,
61ebfedea0SLionel Sambuc * same rsa keys (1024 and 2048)
62ebfedea0SLionel Sambuc * operation performed each eteration sign, verify, encrypt, decrypt on a random bit pattern
63ebfedea0SLionel Sambuc *
64ebfedea0SLionel Sambuc * name 1024 2048 4098
65ebfedea0SLionel Sambuc * =================================
66ebfedea0SLionel Sambuc * gmp: 0.73 6.60 44.80
67ebfedea0SLionel Sambuc * tfm: 2.45 -- --
68ebfedea0SLionel Sambuc * ltm: 3.79 20.74 105.41 (default in hcrypto)
69ebfedea0SLionel Sambuc * openssl: 4.04 11.90 82.59
70ebfedea0SLionel Sambuc * cdsa: 15.89 102.89 721.40
71ebfedea0SLionel Sambuc * imath: 40.62 -- --
72ebfedea0SLionel Sambuc *
73ebfedea0SLionel Sambuc * See the library functions here: @ref hcrypto_rsa
74ebfedea0SLionel Sambuc */
75ebfedea0SLionel Sambuc
76ebfedea0SLionel Sambuc /**
77ebfedea0SLionel Sambuc * Same as RSA_new_method() using NULL as engine.
78ebfedea0SLionel Sambuc *
79ebfedea0SLionel Sambuc * @return a newly allocated RSA object. Free with RSA_free().
80ebfedea0SLionel Sambuc *
81ebfedea0SLionel Sambuc * @ingroup hcrypto_rsa
82ebfedea0SLionel Sambuc */
83ebfedea0SLionel Sambuc
84ebfedea0SLionel Sambuc RSA *
RSA_new(void)85ebfedea0SLionel Sambuc RSA_new(void)
86ebfedea0SLionel Sambuc {
87ebfedea0SLionel Sambuc return RSA_new_method(NULL);
88ebfedea0SLionel Sambuc }
89ebfedea0SLionel Sambuc
90ebfedea0SLionel Sambuc /**
91ebfedea0SLionel Sambuc * Allocate a new RSA object using the engine, if NULL is specified as
92ebfedea0SLionel Sambuc * the engine, use the default RSA engine as returned by
93ebfedea0SLionel Sambuc * ENGINE_get_default_RSA().
94ebfedea0SLionel Sambuc *
95ebfedea0SLionel Sambuc * @param engine Specific what ENGINE RSA provider should be used.
96ebfedea0SLionel Sambuc *
97ebfedea0SLionel Sambuc * @return a newly allocated RSA object. Free with RSA_free().
98ebfedea0SLionel Sambuc *
99ebfedea0SLionel Sambuc * @ingroup hcrypto_rsa
100ebfedea0SLionel Sambuc */
101ebfedea0SLionel Sambuc
102ebfedea0SLionel Sambuc RSA *
RSA_new_method(ENGINE * engine)103ebfedea0SLionel Sambuc RSA_new_method(ENGINE *engine)
104ebfedea0SLionel Sambuc {
105ebfedea0SLionel Sambuc RSA *rsa;
106ebfedea0SLionel Sambuc
107ebfedea0SLionel Sambuc rsa = calloc(1, sizeof(*rsa));
108ebfedea0SLionel Sambuc if (rsa == NULL)
109ebfedea0SLionel Sambuc return NULL;
110ebfedea0SLionel Sambuc
111ebfedea0SLionel Sambuc rsa->references = 1;
112ebfedea0SLionel Sambuc
113ebfedea0SLionel Sambuc if (engine) {
114ebfedea0SLionel Sambuc ENGINE_up_ref(engine);
115ebfedea0SLionel Sambuc rsa->engine = engine;
116ebfedea0SLionel Sambuc } else {
117ebfedea0SLionel Sambuc rsa->engine = ENGINE_get_default_RSA();
118ebfedea0SLionel Sambuc }
119ebfedea0SLionel Sambuc
120ebfedea0SLionel Sambuc if (rsa->engine) {
121ebfedea0SLionel Sambuc rsa->meth = ENGINE_get_RSA(rsa->engine);
122ebfedea0SLionel Sambuc if (rsa->meth == NULL) {
123ebfedea0SLionel Sambuc ENGINE_finish(engine);
124ebfedea0SLionel Sambuc free(rsa);
125ebfedea0SLionel Sambuc return 0;
126ebfedea0SLionel Sambuc }
127ebfedea0SLionel Sambuc }
128ebfedea0SLionel Sambuc
129ebfedea0SLionel Sambuc if (rsa->meth == NULL)
130ebfedea0SLionel Sambuc rsa->meth = rk_UNCONST(RSA_get_default_method());
131ebfedea0SLionel Sambuc
132ebfedea0SLionel Sambuc (*rsa->meth->init)(rsa);
133ebfedea0SLionel Sambuc
134ebfedea0SLionel Sambuc return rsa;
135ebfedea0SLionel Sambuc }
136ebfedea0SLionel Sambuc
137ebfedea0SLionel Sambuc /**
138ebfedea0SLionel Sambuc * Free an allocation RSA object.
139ebfedea0SLionel Sambuc *
140ebfedea0SLionel Sambuc * @param rsa the RSA object to free.
141ebfedea0SLionel Sambuc * @ingroup hcrypto_rsa
142ebfedea0SLionel Sambuc */
143ebfedea0SLionel Sambuc
144ebfedea0SLionel Sambuc void
RSA_free(RSA * rsa)145ebfedea0SLionel Sambuc RSA_free(RSA *rsa)
146ebfedea0SLionel Sambuc {
147ebfedea0SLionel Sambuc if (rsa->references <= 0)
148ebfedea0SLionel Sambuc abort();
149ebfedea0SLionel Sambuc
150ebfedea0SLionel Sambuc if (--rsa->references > 0)
151ebfedea0SLionel Sambuc return;
152ebfedea0SLionel Sambuc
153ebfedea0SLionel Sambuc (*rsa->meth->finish)(rsa);
154ebfedea0SLionel Sambuc
155ebfedea0SLionel Sambuc if (rsa->engine)
156ebfedea0SLionel Sambuc ENGINE_finish(rsa->engine);
157ebfedea0SLionel Sambuc
158ebfedea0SLionel Sambuc #define free_if(f) if (f) { BN_free(f); }
159ebfedea0SLionel Sambuc free_if(rsa->n);
160ebfedea0SLionel Sambuc free_if(rsa->e);
161ebfedea0SLionel Sambuc free_if(rsa->d);
162ebfedea0SLionel Sambuc free_if(rsa->p);
163ebfedea0SLionel Sambuc free_if(rsa->q);
164ebfedea0SLionel Sambuc free_if(rsa->dmp1);
165ebfedea0SLionel Sambuc free_if(rsa->dmq1);
166ebfedea0SLionel Sambuc free_if(rsa->iqmp);
167ebfedea0SLionel Sambuc #undef free_if
168ebfedea0SLionel Sambuc
169ebfedea0SLionel Sambuc memset(rsa, 0, sizeof(*rsa));
170ebfedea0SLionel Sambuc free(rsa);
171ebfedea0SLionel Sambuc }
172ebfedea0SLionel Sambuc
173ebfedea0SLionel Sambuc /**
174ebfedea0SLionel Sambuc * Add an extra reference to the RSA object. The object should be free
175ebfedea0SLionel Sambuc * with RSA_free() to drop the reference.
176ebfedea0SLionel Sambuc *
177ebfedea0SLionel Sambuc * @param rsa the object to add reference counting too.
178ebfedea0SLionel Sambuc *
179ebfedea0SLionel Sambuc * @return the current reference count, can't safely be used except
180ebfedea0SLionel Sambuc * for debug printing.
181ebfedea0SLionel Sambuc *
182ebfedea0SLionel Sambuc * @ingroup hcrypto_rsa
183ebfedea0SLionel Sambuc */
184ebfedea0SLionel Sambuc
185ebfedea0SLionel Sambuc int
RSA_up_ref(RSA * rsa)186ebfedea0SLionel Sambuc RSA_up_ref(RSA *rsa)
187ebfedea0SLionel Sambuc {
188ebfedea0SLionel Sambuc return ++rsa->references;
189ebfedea0SLionel Sambuc }
190ebfedea0SLionel Sambuc
191ebfedea0SLionel Sambuc /**
192ebfedea0SLionel Sambuc * Return the RSA_METHOD used for this RSA object.
193ebfedea0SLionel Sambuc *
194ebfedea0SLionel Sambuc * @param rsa the object to get the method from.
195ebfedea0SLionel Sambuc *
196ebfedea0SLionel Sambuc * @return the method used for this RSA object.
197ebfedea0SLionel Sambuc *
198ebfedea0SLionel Sambuc * @ingroup hcrypto_rsa
199ebfedea0SLionel Sambuc */
200ebfedea0SLionel Sambuc
201ebfedea0SLionel Sambuc const RSA_METHOD *
RSA_get_method(const RSA * rsa)202ebfedea0SLionel Sambuc RSA_get_method(const RSA *rsa)
203ebfedea0SLionel Sambuc {
204ebfedea0SLionel Sambuc return rsa->meth;
205ebfedea0SLionel Sambuc }
206ebfedea0SLionel Sambuc
207ebfedea0SLionel Sambuc /**
208ebfedea0SLionel Sambuc * Set a new method for the RSA keypair.
209ebfedea0SLionel Sambuc *
210ebfedea0SLionel Sambuc * @param rsa rsa parameter.
211ebfedea0SLionel Sambuc * @param method the new method for the RSA parameter.
212ebfedea0SLionel Sambuc *
213ebfedea0SLionel Sambuc * @return 1 on success.
214ebfedea0SLionel Sambuc *
215ebfedea0SLionel Sambuc * @ingroup hcrypto_rsa
216ebfedea0SLionel Sambuc */
217ebfedea0SLionel Sambuc
218ebfedea0SLionel Sambuc int
RSA_set_method(RSA * rsa,const RSA_METHOD * method)219ebfedea0SLionel Sambuc RSA_set_method(RSA *rsa, const RSA_METHOD *method)
220ebfedea0SLionel Sambuc {
221ebfedea0SLionel Sambuc (*rsa->meth->finish)(rsa);
222ebfedea0SLionel Sambuc
223ebfedea0SLionel Sambuc if (rsa->engine) {
224ebfedea0SLionel Sambuc ENGINE_finish(rsa->engine);
225ebfedea0SLionel Sambuc rsa->engine = NULL;
226ebfedea0SLionel Sambuc }
227ebfedea0SLionel Sambuc
228ebfedea0SLionel Sambuc rsa->meth = method;
229ebfedea0SLionel Sambuc (*rsa->meth->init)(rsa);
230ebfedea0SLionel Sambuc return 1;
231ebfedea0SLionel Sambuc }
232ebfedea0SLionel Sambuc
233ebfedea0SLionel Sambuc /**
234ebfedea0SLionel Sambuc * Set the application data for the RSA object.
235ebfedea0SLionel Sambuc *
236ebfedea0SLionel Sambuc * @param rsa the rsa object to set the parameter for
237ebfedea0SLionel Sambuc * @param arg the data object to store
238ebfedea0SLionel Sambuc *
239ebfedea0SLionel Sambuc * @return 1 on success.
240ebfedea0SLionel Sambuc *
241ebfedea0SLionel Sambuc * @ingroup hcrypto_rsa
242ebfedea0SLionel Sambuc */
243ebfedea0SLionel Sambuc
244ebfedea0SLionel Sambuc int
RSA_set_app_data(RSA * rsa,void * arg)245ebfedea0SLionel Sambuc RSA_set_app_data(RSA *rsa, void *arg)
246ebfedea0SLionel Sambuc {
247ebfedea0SLionel Sambuc rsa->ex_data.sk = arg;
248ebfedea0SLionel Sambuc return 1;
249ebfedea0SLionel Sambuc }
250ebfedea0SLionel Sambuc
251ebfedea0SLionel Sambuc /**
252ebfedea0SLionel Sambuc * Get the application data for the RSA object.
253ebfedea0SLionel Sambuc *
254ebfedea0SLionel Sambuc * @param rsa the rsa object to get the parameter for
255ebfedea0SLionel Sambuc *
256ebfedea0SLionel Sambuc * @return the data object
257ebfedea0SLionel Sambuc *
258ebfedea0SLionel Sambuc * @ingroup hcrypto_rsa
259ebfedea0SLionel Sambuc */
260ebfedea0SLionel Sambuc
261ebfedea0SLionel Sambuc void *
RSA_get_app_data(const RSA * rsa)262ebfedea0SLionel Sambuc RSA_get_app_data(const RSA *rsa)
263ebfedea0SLionel Sambuc {
264ebfedea0SLionel Sambuc return rsa->ex_data.sk;
265ebfedea0SLionel Sambuc }
266ebfedea0SLionel Sambuc
267ebfedea0SLionel Sambuc int
RSA_check_key(const RSA * key)268ebfedea0SLionel Sambuc RSA_check_key(const RSA *key)
269ebfedea0SLionel Sambuc {
270ebfedea0SLionel Sambuc static const unsigned char inbuf[] = "hello, world!";
271ebfedea0SLionel Sambuc RSA *rsa = rk_UNCONST(key);
272ebfedea0SLionel Sambuc void *buffer;
273ebfedea0SLionel Sambuc int ret;
274ebfedea0SLionel Sambuc
275ebfedea0SLionel Sambuc /*
276ebfedea0SLionel Sambuc * XXX I have no clue how to implement this w/o a bignum library.
277ebfedea0SLionel Sambuc * Well, when we have a RSA key pair, we can try to encrypt/sign
278ebfedea0SLionel Sambuc * and then decrypt/verify.
279ebfedea0SLionel Sambuc */
280ebfedea0SLionel Sambuc
281ebfedea0SLionel Sambuc if ((rsa->d == NULL || rsa->n == NULL) &&
282ebfedea0SLionel Sambuc (rsa->p == NULL || rsa->q || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL))
283ebfedea0SLionel Sambuc return 0;
284ebfedea0SLionel Sambuc
285ebfedea0SLionel Sambuc buffer = malloc(RSA_size(rsa));
286ebfedea0SLionel Sambuc if (buffer == NULL)
287ebfedea0SLionel Sambuc return 0;
288ebfedea0SLionel Sambuc
289ebfedea0SLionel Sambuc ret = RSA_private_encrypt(sizeof(inbuf), inbuf, buffer,
290ebfedea0SLionel Sambuc rsa, RSA_PKCS1_PADDING);
291ebfedea0SLionel Sambuc if (ret == -1) {
292ebfedea0SLionel Sambuc free(buffer);
293ebfedea0SLionel Sambuc return 0;
294ebfedea0SLionel Sambuc }
295ebfedea0SLionel Sambuc
296ebfedea0SLionel Sambuc ret = RSA_public_decrypt(ret, buffer, buffer,
297ebfedea0SLionel Sambuc rsa, RSA_PKCS1_PADDING);
298ebfedea0SLionel Sambuc if (ret == -1) {
299ebfedea0SLionel Sambuc free(buffer);
300ebfedea0SLionel Sambuc return 0;
301ebfedea0SLionel Sambuc }
302ebfedea0SLionel Sambuc
303ebfedea0SLionel Sambuc if (ret == sizeof(inbuf) && ct_memcmp(buffer, inbuf, sizeof(inbuf)) == 0) {
304ebfedea0SLionel Sambuc free(buffer);
305ebfedea0SLionel Sambuc return 1;
306ebfedea0SLionel Sambuc }
307ebfedea0SLionel Sambuc free(buffer);
308ebfedea0SLionel Sambuc return 0;
309ebfedea0SLionel Sambuc }
310ebfedea0SLionel Sambuc
311ebfedea0SLionel Sambuc int
RSA_size(const RSA * rsa)312ebfedea0SLionel Sambuc RSA_size(const RSA *rsa)
313ebfedea0SLionel Sambuc {
314ebfedea0SLionel Sambuc return BN_num_bytes(rsa->n);
315ebfedea0SLionel Sambuc }
316ebfedea0SLionel Sambuc
317ebfedea0SLionel Sambuc #define RSAFUNC(name, body) \
318ebfedea0SLionel Sambuc int \
319ebfedea0SLionel Sambuc name(int flen,const unsigned char* f, unsigned char* t, RSA* r, int p){\
320ebfedea0SLionel Sambuc return body; \
321ebfedea0SLionel Sambuc }
322ebfedea0SLionel Sambuc
323ebfedea0SLionel Sambuc RSAFUNC(RSA_public_encrypt, (r)->meth->rsa_pub_enc(flen, f, t, r, p))
324ebfedea0SLionel Sambuc RSAFUNC(RSA_public_decrypt, (r)->meth->rsa_pub_dec(flen, f, t, r, p))
325ebfedea0SLionel Sambuc RSAFUNC(RSA_private_encrypt, (r)->meth->rsa_priv_enc(flen, f, t, r, p))
326ebfedea0SLionel Sambuc RSAFUNC(RSA_private_decrypt, (r)->meth->rsa_priv_dec(flen, f, t, r, p))
327ebfedea0SLionel Sambuc
328ebfedea0SLionel Sambuc static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
329ebfedea0SLionel Sambuc
330ebfedea0SLionel Sambuc static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
331ebfedea0SLionel Sambuc static const AlgorithmIdentifier _signature_sha1_data = {
332ebfedea0SLionel Sambuc { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)
333ebfedea0SLionel Sambuc };
334ebfedea0SLionel Sambuc static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
335ebfedea0SLionel Sambuc static const AlgorithmIdentifier _signature_sha256_data = {
336ebfedea0SLionel Sambuc { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
337ebfedea0SLionel Sambuc };
338ebfedea0SLionel Sambuc static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };
339ebfedea0SLionel Sambuc static const AlgorithmIdentifier _signature_md5_data = {
340ebfedea0SLionel Sambuc { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
341ebfedea0SLionel Sambuc };
342ebfedea0SLionel Sambuc
343ebfedea0SLionel Sambuc
344ebfedea0SLionel Sambuc int
RSA_sign(int type,const unsigned char * from,unsigned int flen,unsigned char * to,unsigned int * tlen,RSA * rsa)345ebfedea0SLionel Sambuc RSA_sign(int type, const unsigned char *from, unsigned int flen,
346ebfedea0SLionel Sambuc unsigned char *to, unsigned int *tlen, RSA *rsa)
347ebfedea0SLionel Sambuc {
348ebfedea0SLionel Sambuc if (rsa->meth->rsa_sign)
349ebfedea0SLionel Sambuc return rsa->meth->rsa_sign(type, from, flen, to, tlen, rsa);
350ebfedea0SLionel Sambuc
351ebfedea0SLionel Sambuc if (rsa->meth->rsa_priv_enc) {
352ebfedea0SLionel Sambuc heim_octet_string indata;
353ebfedea0SLionel Sambuc DigestInfo di;
354ebfedea0SLionel Sambuc size_t size;
355ebfedea0SLionel Sambuc int ret;
356ebfedea0SLionel Sambuc
357ebfedea0SLionel Sambuc memset(&di, 0, sizeof(di));
358ebfedea0SLionel Sambuc
359ebfedea0SLionel Sambuc if (type == NID_sha1) {
360ebfedea0SLionel Sambuc di.digestAlgorithm = _signature_sha1_data;
361ebfedea0SLionel Sambuc } else if (type == NID_md5) {
362ebfedea0SLionel Sambuc di.digestAlgorithm = _signature_md5_data;
363ebfedea0SLionel Sambuc } else if (type == NID_sha256) {
364ebfedea0SLionel Sambuc di.digestAlgorithm = _signature_sha256_data;
365ebfedea0SLionel Sambuc } else
366ebfedea0SLionel Sambuc return -1;
367ebfedea0SLionel Sambuc
368ebfedea0SLionel Sambuc di.digest.data = rk_UNCONST(from);
369ebfedea0SLionel Sambuc di.digest.length = flen;
370ebfedea0SLionel Sambuc
371ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(DigestInfo,
372ebfedea0SLionel Sambuc indata.data,
373ebfedea0SLionel Sambuc indata.length,
374ebfedea0SLionel Sambuc &di,
375ebfedea0SLionel Sambuc &size,
376ebfedea0SLionel Sambuc ret);
377ebfedea0SLionel Sambuc if (ret)
378ebfedea0SLionel Sambuc return ret;
379ebfedea0SLionel Sambuc if (indata.length != size)
380ebfedea0SLionel Sambuc abort();
381ebfedea0SLionel Sambuc
382ebfedea0SLionel Sambuc ret = rsa->meth->rsa_priv_enc(indata.length, indata.data, to,
383ebfedea0SLionel Sambuc rsa, RSA_PKCS1_PADDING);
384ebfedea0SLionel Sambuc free(indata.data);
385ebfedea0SLionel Sambuc if (ret > 0) {
386ebfedea0SLionel Sambuc *tlen = ret;
387ebfedea0SLionel Sambuc ret = 1;
388ebfedea0SLionel Sambuc } else
389ebfedea0SLionel Sambuc ret = 0;
390ebfedea0SLionel Sambuc
391ebfedea0SLionel Sambuc return ret;
392ebfedea0SLionel Sambuc }
393ebfedea0SLionel Sambuc
394ebfedea0SLionel Sambuc return 0;
395ebfedea0SLionel Sambuc }
396ebfedea0SLionel Sambuc
397ebfedea0SLionel Sambuc int
RSA_verify(int type,const unsigned char * from,unsigned int flen,unsigned char * sigbuf,unsigned int siglen,RSA * rsa)398ebfedea0SLionel Sambuc RSA_verify(int type, const unsigned char *from, unsigned int flen,
399ebfedea0SLionel Sambuc unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
400ebfedea0SLionel Sambuc {
401ebfedea0SLionel Sambuc if (rsa->meth->rsa_verify)
402ebfedea0SLionel Sambuc return rsa->meth->rsa_verify(type, from, flen, sigbuf, siglen, rsa);
403ebfedea0SLionel Sambuc
404ebfedea0SLionel Sambuc if (rsa->meth->rsa_pub_dec) {
405ebfedea0SLionel Sambuc const AlgorithmIdentifier *digest_alg;
406ebfedea0SLionel Sambuc void *data;
407ebfedea0SLionel Sambuc DigestInfo di;
408ebfedea0SLionel Sambuc size_t size;
409ebfedea0SLionel Sambuc int ret, ret2;
410ebfedea0SLionel Sambuc
411ebfedea0SLionel Sambuc data = malloc(RSA_size(rsa));
412ebfedea0SLionel Sambuc if (data == NULL)
413ebfedea0SLionel Sambuc return -1;
414ebfedea0SLionel Sambuc
415ebfedea0SLionel Sambuc memset(&di, 0, sizeof(di));
416ebfedea0SLionel Sambuc
417ebfedea0SLionel Sambuc ret = rsa->meth->rsa_pub_dec(siglen, sigbuf, data, rsa, RSA_PKCS1_PADDING);
418ebfedea0SLionel Sambuc if (ret <= 0) {
419ebfedea0SLionel Sambuc free(data);
420ebfedea0SLionel Sambuc return -2;
421ebfedea0SLionel Sambuc }
422ebfedea0SLionel Sambuc
423ebfedea0SLionel Sambuc ret2 = decode_DigestInfo(data, ret, &di, &size);
424ebfedea0SLionel Sambuc free(data);
425ebfedea0SLionel Sambuc if (ret2 != 0)
426ebfedea0SLionel Sambuc return -3;
427ebfedea0SLionel Sambuc if (ret != size) {
428ebfedea0SLionel Sambuc free_DigestInfo(&di);
429ebfedea0SLionel Sambuc return -4;
430ebfedea0SLionel Sambuc }
431ebfedea0SLionel Sambuc
432ebfedea0SLionel Sambuc if (flen != di.digest.length || memcmp(di.digest.data, from, flen) != 0) {
433ebfedea0SLionel Sambuc free_DigestInfo(&di);
434ebfedea0SLionel Sambuc return -5;
435ebfedea0SLionel Sambuc }
436ebfedea0SLionel Sambuc
437ebfedea0SLionel Sambuc if (type == NID_sha1) {
438ebfedea0SLionel Sambuc digest_alg = &_signature_sha1_data;
439ebfedea0SLionel Sambuc } else if (type == NID_md5) {
440ebfedea0SLionel Sambuc digest_alg = &_signature_md5_data;
441ebfedea0SLionel Sambuc } else if (type == NID_sha256) {
442ebfedea0SLionel Sambuc digest_alg = &_signature_sha256_data;
443ebfedea0SLionel Sambuc } else {
444ebfedea0SLionel Sambuc free_DigestInfo(&di);
445ebfedea0SLionel Sambuc return -1;
446ebfedea0SLionel Sambuc }
447ebfedea0SLionel Sambuc
448ebfedea0SLionel Sambuc ret = der_heim_oid_cmp(&digest_alg->algorithm,
449ebfedea0SLionel Sambuc &di.digestAlgorithm.algorithm);
450ebfedea0SLionel Sambuc free_DigestInfo(&di);
451ebfedea0SLionel Sambuc
452ebfedea0SLionel Sambuc if (ret != 0)
453ebfedea0SLionel Sambuc return 0;
454ebfedea0SLionel Sambuc return 1;
455ebfedea0SLionel Sambuc }
456ebfedea0SLionel Sambuc
457ebfedea0SLionel Sambuc return 0;
458ebfedea0SLionel Sambuc }
459ebfedea0SLionel Sambuc
460ebfedea0SLionel Sambuc /*
461ebfedea0SLionel Sambuc * A NULL RSA_METHOD that returns failure for all operations. This is
462ebfedea0SLionel Sambuc * used as the default RSA method if we don't have any native
463ebfedea0SLionel Sambuc * support.
464ebfedea0SLionel Sambuc */
465ebfedea0SLionel Sambuc
466ebfedea0SLionel Sambuc static RSAFUNC(null_rsa_public_encrypt, -1)
467ebfedea0SLionel Sambuc static RSAFUNC(null_rsa_public_decrypt, -1)
468ebfedea0SLionel Sambuc static RSAFUNC(null_rsa_private_encrypt, -1)
469ebfedea0SLionel Sambuc static RSAFUNC(null_rsa_private_decrypt, -1)
470ebfedea0SLionel Sambuc
471ebfedea0SLionel Sambuc /*
472ebfedea0SLionel Sambuc *
473ebfedea0SLionel Sambuc */
474ebfedea0SLionel Sambuc
475ebfedea0SLionel Sambuc int
RSA_generate_key_ex(RSA * r,int bits,BIGNUM * e,BN_GENCB * cb)476ebfedea0SLionel Sambuc RSA_generate_key_ex(RSA *r, int bits, BIGNUM *e, BN_GENCB *cb)
477ebfedea0SLionel Sambuc {
478ebfedea0SLionel Sambuc if (r->meth->rsa_keygen)
479ebfedea0SLionel Sambuc return (*r->meth->rsa_keygen)(r, bits, e, cb);
480ebfedea0SLionel Sambuc return 0;
481ebfedea0SLionel Sambuc }
482ebfedea0SLionel Sambuc
483ebfedea0SLionel Sambuc
484ebfedea0SLionel Sambuc /*
485ebfedea0SLionel Sambuc *
486ebfedea0SLionel Sambuc */
487ebfedea0SLionel Sambuc
488ebfedea0SLionel Sambuc static int
null_rsa_init(RSA * rsa)489ebfedea0SLionel Sambuc null_rsa_init(RSA *rsa)
490ebfedea0SLionel Sambuc {
491ebfedea0SLionel Sambuc return 1;
492ebfedea0SLionel Sambuc }
493ebfedea0SLionel Sambuc
494ebfedea0SLionel Sambuc static int
null_rsa_finish(RSA * rsa)495ebfedea0SLionel Sambuc null_rsa_finish(RSA *rsa)
496ebfedea0SLionel Sambuc {
497ebfedea0SLionel Sambuc return 1;
498ebfedea0SLionel Sambuc }
499ebfedea0SLionel Sambuc
500ebfedea0SLionel Sambuc static const RSA_METHOD rsa_null_method = {
501ebfedea0SLionel Sambuc "hcrypto null RSA",
502ebfedea0SLionel Sambuc null_rsa_public_encrypt,
503ebfedea0SLionel Sambuc null_rsa_public_decrypt,
504ebfedea0SLionel Sambuc null_rsa_private_encrypt,
505ebfedea0SLionel Sambuc null_rsa_private_decrypt,
506ebfedea0SLionel Sambuc NULL,
507ebfedea0SLionel Sambuc NULL,
508ebfedea0SLionel Sambuc null_rsa_init,
509ebfedea0SLionel Sambuc null_rsa_finish,
510ebfedea0SLionel Sambuc 0,
511ebfedea0SLionel Sambuc NULL,
512ebfedea0SLionel Sambuc NULL,
513ebfedea0SLionel Sambuc NULL
514ebfedea0SLionel Sambuc };
515ebfedea0SLionel Sambuc
516ebfedea0SLionel Sambuc const RSA_METHOD *
RSA_null_method(void)517ebfedea0SLionel Sambuc RSA_null_method(void)
518ebfedea0SLionel Sambuc {
519ebfedea0SLionel Sambuc return &rsa_null_method;
520ebfedea0SLionel Sambuc }
521ebfedea0SLionel Sambuc
522ebfedea0SLionel Sambuc extern const RSA_METHOD hc_rsa_gmp_method;
523ebfedea0SLionel Sambuc extern const RSA_METHOD hc_rsa_tfm_method;
524ebfedea0SLionel Sambuc extern const RSA_METHOD hc_rsa_ltm_method;
525ebfedea0SLionel Sambuc static const RSA_METHOD *default_rsa_method = &hc_rsa_ltm_method;
526ebfedea0SLionel Sambuc
527ebfedea0SLionel Sambuc
528ebfedea0SLionel Sambuc const RSA_METHOD *
RSA_get_default_method(void)529ebfedea0SLionel Sambuc RSA_get_default_method(void)
530ebfedea0SLionel Sambuc {
531ebfedea0SLionel Sambuc return default_rsa_method;
532ebfedea0SLionel Sambuc }
533ebfedea0SLionel Sambuc
534ebfedea0SLionel Sambuc void
RSA_set_default_method(const RSA_METHOD * meth)535ebfedea0SLionel Sambuc RSA_set_default_method(const RSA_METHOD *meth)
536ebfedea0SLionel Sambuc {
537ebfedea0SLionel Sambuc default_rsa_method = meth;
538ebfedea0SLionel Sambuc }
539ebfedea0SLionel Sambuc
540ebfedea0SLionel Sambuc /*
541ebfedea0SLionel Sambuc *
542ebfedea0SLionel Sambuc */
543ebfedea0SLionel Sambuc
544ebfedea0SLionel Sambuc RSA *
d2i_RSAPrivateKey(RSA * rsa,const unsigned char ** pp,size_t len)545ebfedea0SLionel Sambuc d2i_RSAPrivateKey(RSA *rsa, const unsigned char **pp, size_t len)
546ebfedea0SLionel Sambuc {
547ebfedea0SLionel Sambuc RSAPrivateKey data;
548ebfedea0SLionel Sambuc RSA *k = rsa;
549ebfedea0SLionel Sambuc size_t size;
550ebfedea0SLionel Sambuc int ret;
551ebfedea0SLionel Sambuc
552ebfedea0SLionel Sambuc ret = decode_RSAPrivateKey(*pp, len, &data, &size);
553ebfedea0SLionel Sambuc if (ret)
554ebfedea0SLionel Sambuc return NULL;
555ebfedea0SLionel Sambuc
556ebfedea0SLionel Sambuc *pp += size;
557ebfedea0SLionel Sambuc
558ebfedea0SLionel Sambuc if (k == NULL) {
559ebfedea0SLionel Sambuc k = RSA_new();
560ebfedea0SLionel Sambuc if (k == NULL) {
561ebfedea0SLionel Sambuc free_RSAPrivateKey(&data);
562ebfedea0SLionel Sambuc return NULL;
563ebfedea0SLionel Sambuc }
564ebfedea0SLionel Sambuc }
565ebfedea0SLionel Sambuc
566ebfedea0SLionel Sambuc k->n = _hc_integer_to_BN(&data.modulus, NULL);
567ebfedea0SLionel Sambuc k->e = _hc_integer_to_BN(&data.publicExponent, NULL);
568ebfedea0SLionel Sambuc k->d = _hc_integer_to_BN(&data.privateExponent, NULL);
569ebfedea0SLionel Sambuc k->p = _hc_integer_to_BN(&data.prime1, NULL);
570ebfedea0SLionel Sambuc k->q = _hc_integer_to_BN(&data.prime2, NULL);
571ebfedea0SLionel Sambuc k->dmp1 = _hc_integer_to_BN(&data.exponent1, NULL);
572ebfedea0SLionel Sambuc k->dmq1 = _hc_integer_to_BN(&data.exponent2, NULL);
573ebfedea0SLionel Sambuc k->iqmp = _hc_integer_to_BN(&data.coefficient, NULL);
574ebfedea0SLionel Sambuc free_RSAPrivateKey(&data);
575ebfedea0SLionel Sambuc
576ebfedea0SLionel Sambuc if (k->n == NULL || k->e == NULL || k->d == NULL || k->p == NULL ||
577ebfedea0SLionel Sambuc k->q == NULL || k->dmp1 == NULL || k->dmq1 == NULL || k->iqmp == NULL)
578ebfedea0SLionel Sambuc {
579ebfedea0SLionel Sambuc RSA_free(k);
580ebfedea0SLionel Sambuc return NULL;
581ebfedea0SLionel Sambuc }
582ebfedea0SLionel Sambuc
583ebfedea0SLionel Sambuc return k;
584ebfedea0SLionel Sambuc }
585ebfedea0SLionel Sambuc
586ebfedea0SLionel Sambuc int
i2d_RSAPrivateKey(RSA * rsa,unsigned char ** pp)587ebfedea0SLionel Sambuc i2d_RSAPrivateKey(RSA *rsa, unsigned char **pp)
588ebfedea0SLionel Sambuc {
589ebfedea0SLionel Sambuc RSAPrivateKey data;
590ebfedea0SLionel Sambuc size_t size;
591ebfedea0SLionel Sambuc int ret;
592ebfedea0SLionel Sambuc
593ebfedea0SLionel Sambuc if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL || rsa->p == NULL ||
594ebfedea0SLionel Sambuc rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL ||
595ebfedea0SLionel Sambuc rsa->iqmp == NULL)
596ebfedea0SLionel Sambuc return -1;
597ebfedea0SLionel Sambuc
598ebfedea0SLionel Sambuc memset(&data, 0, sizeof(data));
599ebfedea0SLionel Sambuc
600ebfedea0SLionel Sambuc ret = _hc_BN_to_integer(rsa->n, &data.modulus);
601ebfedea0SLionel Sambuc ret |= _hc_BN_to_integer(rsa->e, &data.publicExponent);
602ebfedea0SLionel Sambuc ret |= _hc_BN_to_integer(rsa->d, &data.privateExponent);
603ebfedea0SLionel Sambuc ret |= _hc_BN_to_integer(rsa->p, &data.prime1);
604ebfedea0SLionel Sambuc ret |= _hc_BN_to_integer(rsa->q, &data.prime2);
605ebfedea0SLionel Sambuc ret |= _hc_BN_to_integer(rsa->dmp1, &data.exponent1);
606ebfedea0SLionel Sambuc ret |= _hc_BN_to_integer(rsa->dmq1, &data.exponent2);
607ebfedea0SLionel Sambuc ret |= _hc_BN_to_integer(rsa->iqmp, &data.coefficient);
608ebfedea0SLionel Sambuc if (ret) {
609ebfedea0SLionel Sambuc free_RSAPrivateKey(&data);
610ebfedea0SLionel Sambuc return -1;
611ebfedea0SLionel Sambuc }
612ebfedea0SLionel Sambuc
613ebfedea0SLionel Sambuc if (pp == NULL) {
614ebfedea0SLionel Sambuc size = length_RSAPrivateKey(&data);
615ebfedea0SLionel Sambuc free_RSAPrivateKey(&data);
616ebfedea0SLionel Sambuc } else {
617ebfedea0SLionel Sambuc void *p;
618ebfedea0SLionel Sambuc size_t len;
619ebfedea0SLionel Sambuc
620ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(RSAPrivateKey, p, len, &data, &size, ret);
621ebfedea0SLionel Sambuc free_RSAPrivateKey(&data);
622ebfedea0SLionel Sambuc if (ret)
623ebfedea0SLionel Sambuc return -1;
624ebfedea0SLionel Sambuc if (len != size)
625ebfedea0SLionel Sambuc abort();
626ebfedea0SLionel Sambuc
627ebfedea0SLionel Sambuc memcpy(*pp, p, size);
628ebfedea0SLionel Sambuc free(p);
629ebfedea0SLionel Sambuc
630ebfedea0SLionel Sambuc *pp += size;
631ebfedea0SLionel Sambuc
632ebfedea0SLionel Sambuc }
633ebfedea0SLionel Sambuc return size;
634ebfedea0SLionel Sambuc }
635ebfedea0SLionel Sambuc
636ebfedea0SLionel Sambuc int
i2d_RSAPublicKey(RSA * rsa,unsigned char ** pp)637ebfedea0SLionel Sambuc i2d_RSAPublicKey(RSA *rsa, unsigned char **pp)
638ebfedea0SLionel Sambuc {
639ebfedea0SLionel Sambuc RSAPublicKey data;
640ebfedea0SLionel Sambuc size_t size;
641ebfedea0SLionel Sambuc int ret;
642ebfedea0SLionel Sambuc
643ebfedea0SLionel Sambuc memset(&data, 0, sizeof(data));
644ebfedea0SLionel Sambuc
645ebfedea0SLionel Sambuc if (_hc_BN_to_integer(rsa->n, &data.modulus) ||
646ebfedea0SLionel Sambuc _hc_BN_to_integer(rsa->e, &data.publicExponent))
647ebfedea0SLionel Sambuc {
648ebfedea0SLionel Sambuc free_RSAPublicKey(&data);
649ebfedea0SLionel Sambuc return -1;
650ebfedea0SLionel Sambuc }
651ebfedea0SLionel Sambuc
652ebfedea0SLionel Sambuc if (pp == NULL) {
653ebfedea0SLionel Sambuc size = length_RSAPublicKey(&data);
654ebfedea0SLionel Sambuc free_RSAPublicKey(&data);
655ebfedea0SLionel Sambuc } else {
656ebfedea0SLionel Sambuc void *p;
657ebfedea0SLionel Sambuc size_t len;
658ebfedea0SLionel Sambuc
659ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(RSAPublicKey, p, len, &data, &size, ret);
660ebfedea0SLionel Sambuc free_RSAPublicKey(&data);
661ebfedea0SLionel Sambuc if (ret)
662ebfedea0SLionel Sambuc return -1;
663ebfedea0SLionel Sambuc if (len != size)
664ebfedea0SLionel Sambuc abort();
665ebfedea0SLionel Sambuc
666ebfedea0SLionel Sambuc memcpy(*pp, p, size);
667ebfedea0SLionel Sambuc free(p);
668ebfedea0SLionel Sambuc
669ebfedea0SLionel Sambuc *pp += size;
670ebfedea0SLionel Sambuc }
671ebfedea0SLionel Sambuc
672ebfedea0SLionel Sambuc return size;
673ebfedea0SLionel Sambuc }
674ebfedea0SLionel Sambuc
675ebfedea0SLionel Sambuc RSA *
d2i_RSAPublicKey(RSA * rsa,const unsigned char ** pp,size_t len)676ebfedea0SLionel Sambuc d2i_RSAPublicKey(RSA *rsa, const unsigned char **pp, size_t len)
677ebfedea0SLionel Sambuc {
678ebfedea0SLionel Sambuc RSAPublicKey data;
679ebfedea0SLionel Sambuc RSA *k = rsa;
680ebfedea0SLionel Sambuc size_t size;
681ebfedea0SLionel Sambuc int ret;
682ebfedea0SLionel Sambuc
683ebfedea0SLionel Sambuc ret = decode_RSAPublicKey(*pp, len, &data, &size);
684ebfedea0SLionel Sambuc if (ret)
685ebfedea0SLionel Sambuc return NULL;
686ebfedea0SLionel Sambuc
687ebfedea0SLionel Sambuc *pp += size;
688ebfedea0SLionel Sambuc
689ebfedea0SLionel Sambuc if (k == NULL) {
690ebfedea0SLionel Sambuc k = RSA_new();
691ebfedea0SLionel Sambuc if (k == NULL) {
692ebfedea0SLionel Sambuc free_RSAPublicKey(&data);
693ebfedea0SLionel Sambuc return NULL;
694ebfedea0SLionel Sambuc }
695ebfedea0SLionel Sambuc }
696ebfedea0SLionel Sambuc
697ebfedea0SLionel Sambuc k->n = _hc_integer_to_BN(&data.modulus, NULL);
698ebfedea0SLionel Sambuc k->e = _hc_integer_to_BN(&data.publicExponent, NULL);
699ebfedea0SLionel Sambuc
700ebfedea0SLionel Sambuc free_RSAPublicKey(&data);
701ebfedea0SLionel Sambuc
702ebfedea0SLionel Sambuc if (k->n == NULL || k->e == NULL) {
703ebfedea0SLionel Sambuc RSA_free(k);
704ebfedea0SLionel Sambuc return NULL;
705ebfedea0SLionel Sambuc }
706ebfedea0SLionel Sambuc
707ebfedea0SLionel Sambuc return k;
708ebfedea0SLionel Sambuc }
709