xref: /minix3/crypto/external/bsd/heimdal/dist/lib/hcrypto/rsa.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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