e_ubsec.c revision 296465
1/* crypto/engine/hw_ubsec.c */
2/*
3 * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
4 * 2000. Cloned shamelessly by Joe Tardo.
5 */
6/* ====================================================================
7 * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 *    software must display the following acknowledgment:
23 *    "This product includes software developed by the OpenSSL Project
24 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 *    endorse or promote products derived from this software without
28 *    prior written permission. For written permission, please contact
29 *    licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 *    nor may "OpenSSL" appear in their names without prior written
33 *    permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 *    acknowledgment:
37 *    "This product includes software developed by the OpenSSL Project
38 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com).  This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
57 *
58 */
59
60#include <stdio.h>
61#include <string.h>
62#include <openssl/crypto.h>
63#include <openssl/buffer.h>
64#include <openssl/dso.h>
65#include <openssl/engine.h>
66#ifndef OPENSSL_NO_RSA
67# include <openssl/rsa.h>
68#endif
69#ifndef OPENSSL_NO_DSA
70# include <openssl/dsa.h>
71#endif
72#ifndef OPENSSL_NO_DH
73# include <openssl/dh.h>
74#endif
75#include <openssl/bn.h>
76
77#ifndef OPENSSL_NO_HW
78# ifndef OPENSSL_NO_HW_UBSEC
79
80#  ifdef FLAT_INC
81#   include "hw_ubsec.h"
82#  else
83#   include "vendor_defns/hw_ubsec.h"
84#  endif
85
86#  define UBSEC_LIB_NAME "ubsec engine"
87#  include "e_ubsec_err.c"
88
89#  define FAIL_TO_SOFTWARE -15
90
91static int ubsec_destroy(ENGINE *e);
92static int ubsec_init(ENGINE *e);
93static int ubsec_finish(ENGINE *e);
94static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void));
95static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
96                         const BIGNUM *m, BN_CTX *ctx);
97static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
98                             const BIGNUM *q, const BIGNUM *dp,
99                             const BIGNUM *dq, const BIGNUM *qinv,
100                             BN_CTX *ctx);
101#  ifndef OPENSSL_NO_RSA
102static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
103                             BN_CTX *ctx);
104#  endif
105static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
106                              const BIGNUM *m, BN_CTX *ctx,
107                              BN_MONT_CTX *m_ctx);
108#  ifndef OPENSSL_NO_DSA
109#   ifdef NOT_USED
110static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
111                             BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
112                             BN_CTX *ctx, BN_MONT_CTX *in_mont);
113static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
114                             const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
115                             BN_MONT_CTX *m_ctx);
116#   endif
117static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen,
118                                  DSA *dsa);
119static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
120                            DSA_SIG *sig, DSA *dsa);
121#  endif
122#  ifndef OPENSSL_NO_DH
123static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
124                            const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
125                            BN_MONT_CTX *m_ctx);
126static int ubsec_dh_compute_key(unsigned char *key, const BIGNUM *pub_key,
127                                DH *dh);
128static int ubsec_dh_generate_key(DH *dh);
129#  endif
130
131#  ifdef NOT_USED
132static int ubsec_rand_bytes(unsigned char *buf, int num);
133static int ubsec_rand_status(void);
134#  endif
135
136#  define UBSEC_CMD_SO_PATH               ENGINE_CMD_BASE
137static const ENGINE_CMD_DEFN ubsec_cmd_defns[] = {
138    {UBSEC_CMD_SO_PATH,
139     "SO_PATH",
140     "Specifies the path to the 'ubsec' shared library",
141     ENGINE_CMD_FLAG_STRING},
142    {0, NULL, NULL, 0}
143};
144
145#  ifndef OPENSSL_NO_RSA
146/* Our internal RSA_METHOD that we provide pointers to */
147static RSA_METHOD ubsec_rsa = {
148    "UBSEC RSA method",
149    NULL,
150    NULL,
151    NULL,
152    NULL,
153    ubsec_rsa_mod_exp,
154    ubsec_mod_exp_mont,
155    NULL,
156    NULL,
157    0,
158    NULL,
159    NULL,
160    NULL,
161    NULL
162};
163#  endif
164
165#  ifndef OPENSSL_NO_DSA
166/* Our internal DSA_METHOD that we provide pointers to */
167static DSA_METHOD ubsec_dsa = {
168    "UBSEC DSA method",
169    ubsec_dsa_do_sign,          /* dsa_do_sign */
170    NULL,                       /* dsa_sign_setup */
171    ubsec_dsa_verify,           /* dsa_do_verify */
172    NULL,                       /* ubsec_dsa_mod_exp *//* dsa_mod_exp */
173    NULL,                       /* ubsec_mod_exp_dsa *//* bn_mod_exp */
174    NULL,                       /* init */
175    NULL,                       /* finish */
176    0,                          /* flags */
177    NULL,                       /* app_data */
178    NULL,                       /* dsa_paramgen */
179    NULL                        /* dsa_keygen */
180};
181#  endif
182
183#  ifndef OPENSSL_NO_DH
184/* Our internal DH_METHOD that we provide pointers to */
185static DH_METHOD ubsec_dh = {
186    "UBSEC DH method",
187    ubsec_dh_generate_key,
188    ubsec_dh_compute_key,
189    ubsec_mod_exp_dh,
190    NULL,
191    NULL,
192    0,
193    NULL,
194    NULL
195};
196#  endif
197
198/* Constants used when creating the ENGINE */
199static const char *engine_ubsec_id = "ubsec";
200static const char *engine_ubsec_name = "UBSEC hardware engine support";
201
202/*
203 * This internal function is used by ENGINE_ubsec() and possibly by the
204 * "dynamic" ENGINE support too
205 */
206static int bind_helper(ENGINE *e)
207{
208#  ifndef OPENSSL_NO_RSA
209    const RSA_METHOD *meth1;
210#  endif
211#  ifndef OPENSSL_NO_DH
212#   ifndef HAVE_UBSEC_DH
213    const DH_METHOD *meth3;
214#   endif                       /* HAVE_UBSEC_DH */
215#  endif
216    if (!ENGINE_set_id(e, engine_ubsec_id) ||
217        !ENGINE_set_name(e, engine_ubsec_name) ||
218#  ifndef OPENSSL_NO_RSA
219        !ENGINE_set_RSA(e, &ubsec_rsa) ||
220#  endif
221#  ifndef OPENSSL_NO_DSA
222        !ENGINE_set_DSA(e, &ubsec_dsa) ||
223#  endif
224#  ifndef OPENSSL_NO_DH
225        !ENGINE_set_DH(e, &ubsec_dh) ||
226#  endif
227        !ENGINE_set_destroy_function(e, ubsec_destroy) ||
228        !ENGINE_set_init_function(e, ubsec_init) ||
229        !ENGINE_set_finish_function(e, ubsec_finish) ||
230        !ENGINE_set_ctrl_function(e, ubsec_ctrl) ||
231        !ENGINE_set_cmd_defns(e, ubsec_cmd_defns))
232        return 0;
233
234#  ifndef OPENSSL_NO_RSA
235    /*
236     * We know that the "PKCS1_SSLeay()" functions hook properly to the
237     * Broadcom-specific mod_exp and mod_exp_crt so we use those functions.
238     * NB: We don't use ENGINE_openssl() or anything "more generic" because
239     * something like the RSAref code may not hook properly, and if you own
240     * one of these cards then you have the right to do RSA operations on it
241     * anyway!
242     */
243    meth1 = RSA_PKCS1_SSLeay();
244    ubsec_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
245    ubsec_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
246    ubsec_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
247    ubsec_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
248#  endif
249
250#  ifndef OPENSSL_NO_DH
251#   ifndef HAVE_UBSEC_DH
252    /* Much the same for Diffie-Hellman */
253    meth3 = DH_OpenSSL();
254    ubsec_dh.generate_key = meth3->generate_key;
255    ubsec_dh.compute_key = meth3->compute_key;
256#   endif                       /* HAVE_UBSEC_DH */
257#  endif
258
259    /* Ensure the ubsec error handling is set up */
260    ERR_load_UBSEC_strings();
261    return 1;
262}
263
264#  ifdef OPENSSL_NO_DYNAMIC_ENGINE
265static ENGINE *engine_ubsec(void)
266{
267    ENGINE *ret = ENGINE_new();
268    if (!ret)
269        return NULL;
270    if (!bind_helper(ret)) {
271        ENGINE_free(ret);
272        return NULL;
273    }
274    return ret;
275}
276
277void ENGINE_load_ubsec(void)
278{
279    /* Copied from eng_[openssl|dyn].c */
280    ENGINE *toadd = engine_ubsec();
281    if (!toadd)
282        return;
283    ENGINE_add(toadd);
284    ENGINE_free(toadd);
285    ERR_clear_error();
286}
287#  endif
288
289/*
290 * This is a process-global DSO handle used for loading and unloading the
291 * UBSEC library. NB: This is only set (or unset) during an init() or
292 * finish() call (reference counts permitting) and they're operating with
293 * global locks, so this should be thread-safe implicitly.
294 */
295
296static DSO *ubsec_dso = NULL;
297
298/*
299 * These are the function pointers that are (un)set when the library has
300 * successfully (un)loaded.
301 */
302
303static t_UBSEC_ubsec_bytes_to_bits *p_UBSEC_ubsec_bytes_to_bits = NULL;
304static t_UBSEC_ubsec_bits_to_bytes *p_UBSEC_ubsec_bits_to_bytes = NULL;
305static t_UBSEC_ubsec_open *p_UBSEC_ubsec_open = NULL;
306static t_UBSEC_ubsec_close *p_UBSEC_ubsec_close = NULL;
307#  ifndef OPENSSL_NO_DH
308static t_UBSEC_diffie_hellman_generate_ioctl
309    * p_UBSEC_diffie_hellman_generate_ioctl = NULL;
310static t_UBSEC_diffie_hellman_agree_ioctl *p_UBSEC_diffie_hellman_agree_ioctl
311    = NULL;
312#  endif
313/* #ifndef OPENSSL_NO_RSA */
314static t_UBSEC_rsa_mod_exp_ioctl *p_UBSEC_rsa_mod_exp_ioctl = NULL;
315static t_UBSEC_rsa_mod_exp_crt_ioctl *p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
316/* #endif */
317#  ifndef OPENSSL_NO_DSA
318static t_UBSEC_dsa_sign_ioctl *p_UBSEC_dsa_sign_ioctl = NULL;
319static t_UBSEC_dsa_verify_ioctl *p_UBSEC_dsa_verify_ioctl = NULL;
320#  endif
321static t_UBSEC_math_accelerate_ioctl *p_UBSEC_math_accelerate_ioctl = NULL;
322static t_UBSEC_rng_ioctl *p_UBSEC_rng_ioctl = NULL;
323static t_UBSEC_max_key_len_ioctl *p_UBSEC_max_key_len_ioctl = NULL;
324
325static int max_key_len = 1024;  /* ??? */
326
327/*
328 * These are the static string constants for the DSO file name and the function
329 * symbol names to bind to.
330 */
331
332static const char *UBSEC_LIBNAME = NULL;
333static const char *get_UBSEC_LIBNAME(void)
334{
335    if (UBSEC_LIBNAME)
336        return UBSEC_LIBNAME;
337    return "ubsec";
338}
339
340static void free_UBSEC_LIBNAME(void)
341{
342    if (UBSEC_LIBNAME)
343        OPENSSL_free((void *)UBSEC_LIBNAME);
344    UBSEC_LIBNAME = NULL;
345}
346
347static long set_UBSEC_LIBNAME(const char *name)
348{
349    free_UBSEC_LIBNAME();
350    return (((UBSEC_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
351}
352
353static const char *UBSEC_F1 = "ubsec_bytes_to_bits";
354static const char *UBSEC_F2 = "ubsec_bits_to_bytes";
355static const char *UBSEC_F3 = "ubsec_open";
356static const char *UBSEC_F4 = "ubsec_close";
357#  ifndef OPENSSL_NO_DH
358static const char *UBSEC_F5 = "diffie_hellman_generate_ioctl";
359static const char *UBSEC_F6 = "diffie_hellman_agree_ioctl";
360#  endif
361/* #ifndef OPENSSL_NO_RSA */
362static const char *UBSEC_F7 = "rsa_mod_exp_ioctl";
363static const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl";
364/* #endif */
365#  ifndef OPENSSL_NO_DSA
366static const char *UBSEC_F9 = "dsa_sign_ioctl";
367static const char *UBSEC_F10 = "dsa_verify_ioctl";
368#  endif
369static const char *UBSEC_F11 = "math_accelerate_ioctl";
370static const char *UBSEC_F12 = "rng_ioctl";
371static const char *UBSEC_F13 = "ubsec_max_key_len_ioctl";
372
373/* Destructor (complements the "ENGINE_ubsec()" constructor) */
374static int ubsec_destroy(ENGINE *e)
375{
376    free_UBSEC_LIBNAME();
377    ERR_unload_UBSEC_strings();
378    return 1;
379}
380
381/* (de)initialisation functions. */
382static int ubsec_init(ENGINE *e)
383{
384    t_UBSEC_ubsec_bytes_to_bits *p1;
385    t_UBSEC_ubsec_bits_to_bytes *p2;
386    t_UBSEC_ubsec_open *p3;
387    t_UBSEC_ubsec_close *p4;
388#  ifndef OPENSSL_NO_DH
389    t_UBSEC_diffie_hellman_generate_ioctl *p5;
390    t_UBSEC_diffie_hellman_agree_ioctl *p6;
391#  endif
392/* #ifndef OPENSSL_NO_RSA */
393    t_UBSEC_rsa_mod_exp_ioctl *p7;
394    t_UBSEC_rsa_mod_exp_crt_ioctl *p8;
395/* #endif */
396#  ifndef OPENSSL_NO_DSA
397    t_UBSEC_dsa_sign_ioctl *p9;
398    t_UBSEC_dsa_verify_ioctl *p10;
399#  endif
400    t_UBSEC_math_accelerate_ioctl *p11;
401    t_UBSEC_rng_ioctl *p12;
402    t_UBSEC_max_key_len_ioctl *p13;
403    int fd = 0;
404
405    if (ubsec_dso != NULL) {
406        UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_ALREADY_LOADED);
407        goto err;
408    }
409    /*
410     * Attempt to load libubsec.so/ubsec.dll/whatever.
411     */
412    ubsec_dso = DSO_load(NULL, get_UBSEC_LIBNAME(), NULL, 0);
413    if (ubsec_dso == NULL) {
414        UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
415        goto err;
416    }
417
418    if (!(p1 = (t_UBSEC_ubsec_bytes_to_bits *)
419          DSO_bind_func(ubsec_dso, UBSEC_F1))
420        || !(p2 = (t_UBSEC_ubsec_bits_to_bytes *)
421             DSO_bind_func(ubsec_dso, UBSEC_F2))
422        || !(p3 = (t_UBSEC_ubsec_open *)
423             DSO_bind_func(ubsec_dso, UBSEC_F3))
424        || !(p4 = (t_UBSEC_ubsec_close *)
425             DSO_bind_func(ubsec_dso, UBSEC_F4))
426#  ifndef OPENSSL_NO_DH
427        || !(p5 = (t_UBSEC_diffie_hellman_generate_ioctl *)
428             DSO_bind_func(ubsec_dso, UBSEC_F5))
429        || !(p6 = (t_UBSEC_diffie_hellman_agree_ioctl *)
430             DSO_bind_func(ubsec_dso, UBSEC_F6))
431#  endif
432/* #ifndef OPENSSL_NO_RSA */
433        || !(p7 = (t_UBSEC_rsa_mod_exp_ioctl *)
434             DSO_bind_func(ubsec_dso, UBSEC_F7))
435        || !(p8 = (t_UBSEC_rsa_mod_exp_crt_ioctl *)
436             DSO_bind_func(ubsec_dso, UBSEC_F8))
437/* #endif */
438#  ifndef OPENSSL_NO_DSA
439        || !(p9 = (t_UBSEC_dsa_sign_ioctl *)
440             DSO_bind_func(ubsec_dso, UBSEC_F9))
441        || !(p10 = (t_UBSEC_dsa_verify_ioctl *)
442             DSO_bind_func(ubsec_dso, UBSEC_F10))
443#  endif
444        || !(p11 = (t_UBSEC_math_accelerate_ioctl *)
445             DSO_bind_func(ubsec_dso, UBSEC_F11))
446        || !(p12 = (t_UBSEC_rng_ioctl *)
447             DSO_bind_func(ubsec_dso, UBSEC_F12))
448        || !(p13 = (t_UBSEC_max_key_len_ioctl *)
449             DSO_bind_func(ubsec_dso, UBSEC_F13))) {
450        UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
451        goto err;
452    }
453
454    /* Copy the pointers */
455    p_UBSEC_ubsec_bytes_to_bits = p1;
456    p_UBSEC_ubsec_bits_to_bytes = p2;
457    p_UBSEC_ubsec_open = p3;
458    p_UBSEC_ubsec_close = p4;
459#  ifndef OPENSSL_NO_DH
460    p_UBSEC_diffie_hellman_generate_ioctl = p5;
461    p_UBSEC_diffie_hellman_agree_ioctl = p6;
462#  endif
463#  ifndef OPENSSL_NO_RSA
464    p_UBSEC_rsa_mod_exp_ioctl = p7;
465    p_UBSEC_rsa_mod_exp_crt_ioctl = p8;
466#  endif
467#  ifndef OPENSSL_NO_DSA
468    p_UBSEC_dsa_sign_ioctl = p9;
469    p_UBSEC_dsa_verify_ioctl = p10;
470#  endif
471    p_UBSEC_math_accelerate_ioctl = p11;
472    p_UBSEC_rng_ioctl = p12;
473    p_UBSEC_max_key_len_ioctl = p13;
474
475    /* Perform an open to see if there's actually any unit running. */
476    if (((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0)
477        && (p_UBSEC_max_key_len_ioctl(fd, &max_key_len) == 0)) {
478        p_UBSEC_ubsec_close(fd);
479        return 1;
480    } else {
481        UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
482    }
483
484 err:
485    if (ubsec_dso)
486        DSO_free(ubsec_dso);
487    ubsec_dso = NULL;
488    p_UBSEC_ubsec_bytes_to_bits = NULL;
489    p_UBSEC_ubsec_bits_to_bytes = NULL;
490    p_UBSEC_ubsec_open = NULL;
491    p_UBSEC_ubsec_close = NULL;
492#  ifndef OPENSSL_NO_DH
493    p_UBSEC_diffie_hellman_generate_ioctl = NULL;
494    p_UBSEC_diffie_hellman_agree_ioctl = NULL;
495#  endif
496#  ifndef OPENSSL_NO_RSA
497    p_UBSEC_rsa_mod_exp_ioctl = NULL;
498    p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
499#  endif
500#  ifndef OPENSSL_NO_DSA
501    p_UBSEC_dsa_sign_ioctl = NULL;
502    p_UBSEC_dsa_verify_ioctl = NULL;
503#  endif
504    p_UBSEC_math_accelerate_ioctl = NULL;
505    p_UBSEC_rng_ioctl = NULL;
506    p_UBSEC_max_key_len_ioctl = NULL;
507
508    return 0;
509}
510
511static int ubsec_finish(ENGINE *e)
512{
513    free_UBSEC_LIBNAME();
514    if (ubsec_dso == NULL) {
515        UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_NOT_LOADED);
516        return 0;
517    }
518    if (!DSO_free(ubsec_dso)) {
519        UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_DSO_FAILURE);
520        return 0;
521    }
522    ubsec_dso = NULL;
523    p_UBSEC_ubsec_bytes_to_bits = NULL;
524    p_UBSEC_ubsec_bits_to_bytes = NULL;
525    p_UBSEC_ubsec_open = NULL;
526    p_UBSEC_ubsec_close = NULL;
527#  ifndef OPENSSL_NO_DH
528    p_UBSEC_diffie_hellman_generate_ioctl = NULL;
529    p_UBSEC_diffie_hellman_agree_ioctl = NULL;
530#  endif
531#  ifndef OPENSSL_NO_RSA
532    p_UBSEC_rsa_mod_exp_ioctl = NULL;
533    p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
534#  endif
535#  ifndef OPENSSL_NO_DSA
536    p_UBSEC_dsa_sign_ioctl = NULL;
537    p_UBSEC_dsa_verify_ioctl = NULL;
538#  endif
539    p_UBSEC_math_accelerate_ioctl = NULL;
540    p_UBSEC_rng_ioctl = NULL;
541    p_UBSEC_max_key_len_ioctl = NULL;
542    return 1;
543}
544
545static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
546{
547    int initialised = ((ubsec_dso == NULL) ? 0 : 1);
548    switch (cmd) {
549    case UBSEC_CMD_SO_PATH:
550        if (p == NULL) {
551            UBSECerr(UBSEC_F_UBSEC_CTRL, ERR_R_PASSED_NULL_PARAMETER);
552            return 0;
553        }
554        if (initialised) {
555            UBSECerr(UBSEC_F_UBSEC_CTRL, UBSEC_R_ALREADY_LOADED);
556            return 0;
557        }
558        return set_UBSEC_LIBNAME((const char *)p);
559    default:
560        break;
561    }
562    UBSECerr(UBSEC_F_UBSEC_CTRL, UBSEC_R_CTRL_COMMAND_NOT_IMPLEMENTED);
563    return 0;
564}
565
566static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
567                         const BIGNUM *m, BN_CTX *ctx)
568{
569    int y_len = 0;
570    int fd;
571
572    if (ubsec_dso == NULL) {
573        UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_NOT_LOADED);
574        return 0;
575    }
576
577    /* Check if hardware can't handle this argument. */
578    y_len = BN_num_bits(m);
579    if (y_len > max_key_len) {
580        UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
581        return BN_mod_exp(r, a, p, m, ctx);
582    }
583
584    if (!bn_wexpand(r, m->top)) {
585        UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_BN_EXPAND_FAIL);
586        return 0;
587    }
588
589    if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
590        fd = 0;
591        UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_UNIT_FAILURE);
592        return BN_mod_exp(r, a, p, m, ctx);
593    }
594
595    if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a),
596                                  (unsigned char *)m->d, BN_num_bits(m),
597                                  (unsigned char *)p->d, BN_num_bits(p),
598                                  (unsigned char *)r->d, &y_len) != 0) {
599        UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED);
600        p_UBSEC_ubsec_close(fd);
601
602        return BN_mod_exp(r, a, p, m, ctx);
603    }
604
605    p_UBSEC_ubsec_close(fd);
606
607    r->top = (BN_num_bits(m) + BN_BITS2 - 1) / BN_BITS2;
608    return 1;
609}
610
611#  ifndef OPENSSL_NO_RSA
612static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
613                             BN_CTX *ctx)
614{
615    int to_return = 0;
616
617    if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
618        UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP, UBSEC_R_MISSING_KEY_COMPONENTS);
619        goto err;
620    }
621
622    to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
623                                  rsa->dmq1, rsa->iqmp, ctx);
624    if (to_return == FAIL_TO_SOFTWARE) {
625        /*
626         * Do in software as hardware failed.
627         */
628        const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
629        to_return = (*meth->rsa_mod_exp) (r0, I, rsa, ctx);
630    }
631 err:
632    return to_return;
633}
634#  endif
635
636static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
637                             const BIGNUM *q, const BIGNUM *dp,
638                             const BIGNUM *dq, const BIGNUM *qinv,
639                             BN_CTX *ctx)
640{
641    int y_len, fd;
642
643    y_len = BN_num_bits(p) + BN_num_bits(q);
644
645    /* Check if hardware can't handle this argument. */
646    if (y_len > max_key_len) {
647        UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT,
648                 UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
649        return FAIL_TO_SOFTWARE;
650    }
651
652    if (!bn_wexpand(r, p->top + q->top + 1)) {
653        UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_BN_EXPAND_FAIL);
654        return 0;
655    }
656
657    if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
658        fd = 0;
659        UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_UNIT_FAILURE);
660        return FAIL_TO_SOFTWARE;
661    }
662
663    if (p_UBSEC_rsa_mod_exp_crt_ioctl(fd,
664                                      (unsigned char *)a->d, BN_num_bits(a),
665                                      (unsigned char *)qinv->d,
666                                      BN_num_bits(qinv),
667                                      (unsigned char *)dp->d, BN_num_bits(dp),
668                                      (unsigned char *)p->d, BN_num_bits(p),
669                                      (unsigned char *)dq->d, BN_num_bits(dq),
670                                      (unsigned char *)q->d, BN_num_bits(q),
671                                      (unsigned char *)r->d, &y_len) != 0) {
672        UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_REQUEST_FAILED);
673        p_UBSEC_ubsec_close(fd);
674        return FAIL_TO_SOFTWARE;
675    }
676
677    p_UBSEC_ubsec_close(fd);
678
679    r->top = (BN_num_bits(p) + BN_num_bits(q) + BN_BITS2 - 1) / BN_BITS2;
680    return 1;
681}
682
683#  ifndef OPENSSL_NO_DSA
684#   ifdef NOT_USED
685static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
686                             BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
687                             BN_CTX *ctx, BN_MONT_CTX *in_mont)
688{
689    BIGNUM t;
690    int to_return = 0;
691
692    BN_init(&t);
693    /* let rr = a1 ^ p1 mod m */
694    if (!ubsec_mod_exp(rr, a1, p1, m, ctx))
695        goto end;
696    /* let t = a2 ^ p2 mod m */
697    if (!ubsec_mod_exp(&t, a2, p2, m, ctx))
698        goto end;
699    /* let rr = rr * t mod m */
700    if (!BN_mod_mul(rr, rr, &t, m, ctx))
701        goto end;
702    to_return = 1;
703 end:
704    BN_free(&t);
705    return to_return;
706}
707
708static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
709                             const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
710                             BN_MONT_CTX *m_ctx)
711{
712    return ubsec_mod_exp(r, a, p, m, ctx);
713}
714#   endif
715#  endif
716
717/*
718 * This function is aliased to mod_exp (with the mont stuff dropped).
719 */
720static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
721                              const BIGNUM *m, BN_CTX *ctx,
722                              BN_MONT_CTX *m_ctx)
723{
724    int ret = 0;
725
726#  ifndef OPENSSL_NO_RSA
727    /* Do in software if the key is too large for the hardware. */
728    if (BN_num_bits(m) > max_key_len) {
729        const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
730        ret = (*meth->bn_mod_exp) (r, a, p, m, ctx, m_ctx);
731    } else
732#  endif
733    {
734        ret = ubsec_mod_exp(r, a, p, m, ctx);
735    }
736
737    return ret;
738}
739
740#  ifndef OPENSSL_NO_DH
741/* This function is aliased to mod_exp (with the dh and mont dropped). */
742static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
743                            const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
744                            BN_MONT_CTX *m_ctx)
745{
746    return ubsec_mod_exp(r, a, p, m, ctx);
747}
748#  endif
749
750#  ifndef OPENSSL_NO_DSA
751static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen,
752                                  DSA *dsa)
753{
754    DSA_SIG *to_return = NULL;
755    int s_len = 160, r_len = 160, d_len, fd;
756    BIGNUM m, *r = NULL, *s = NULL;
757
758    BN_init(&m);
759
760    s = BN_new();
761    r = BN_new();
762    if ((s == NULL) || (r == NULL))
763        goto err;
764
765    d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dlen);
766
767    if (!bn_wexpand(r, (160 + BN_BITS2 - 1) / BN_BITS2) ||
768        (!bn_wexpand(s, (160 + BN_BITS2 - 1) / BN_BITS2))) {
769        UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL);
770        goto err;
771    }
772
773    if (BN_bin2bn(dgst, dlen, &m) == NULL) {
774        UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL);
775        goto err;
776    }
777
778    if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
779        const DSA_METHOD *meth;
780        fd = 0;
781        UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_UNIT_FAILURE);
782        meth = DSA_OpenSSL();
783        to_return = meth->dsa_do_sign(dgst, dlen, dsa);
784        goto err;
785    }
786
787    if (p_UBSEC_dsa_sign_ioctl(fd,
788                               /* compute hash before signing */
789                               0, (unsigned char *)dgst, d_len, NULL,
790                               /* compute random value */
791                               0,
792                               (unsigned char *)dsa->p->d,
793                               BN_num_bits(dsa->p),
794                               (unsigned char *)dsa->q->d,
795                               BN_num_bits(dsa->q),
796                               (unsigned char *)dsa->g->d,
797                               BN_num_bits(dsa->g),
798                               (unsigned char *)dsa->priv_key->d,
799                               BN_num_bits(dsa->priv_key),
800                               (unsigned char *)r->d, &r_len,
801                               (unsigned char *)s->d, &s_len) != 0) {
802        const DSA_METHOD *meth;
803
804        UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_REQUEST_FAILED);
805        p_UBSEC_ubsec_close(fd);
806        meth = DSA_OpenSSL();
807        to_return = meth->dsa_do_sign(dgst, dlen, dsa);
808
809        goto err;
810    }
811
812    p_UBSEC_ubsec_close(fd);
813
814    r->top = (160 + BN_BITS2 - 1) / BN_BITS2;
815    s->top = (160 + BN_BITS2 - 1) / BN_BITS2;
816
817    to_return = DSA_SIG_new();
818    if (to_return == NULL) {
819        UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL);
820        goto err;
821    }
822
823    to_return->r = r;
824    to_return->s = s;
825
826 err:
827    if (!to_return) {
828        if (r)
829            BN_free(r);
830        if (s)
831            BN_free(s);
832    }
833    BN_clear_free(&m);
834    return to_return;
835}
836
837static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
838                            DSA_SIG *sig, DSA *dsa)
839{
840    int v_len, d_len;
841    int to_return = 0;
842    int fd;
843    BIGNUM v, *pv = &v;
844
845    BN_init(&v);
846
847    if (!bn_wexpand(pv, dsa->p->top)) {
848        UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_BN_EXPAND_FAIL);
849        goto err;
850    }
851
852    v_len = BN_num_bits(dsa->p);
853
854    d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dgst_len);
855
856    if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
857        const DSA_METHOD *meth;
858        fd = 0;
859        UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_UNIT_FAILURE);
860        meth = DSA_OpenSSL();
861        to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
862        goto err;
863    }
864
865    if (p_UBSEC_dsa_verify_ioctl(fd, 0, /* compute hash before signing */
866                                 (unsigned char *)dgst, d_len,
867                                 (unsigned char *)dsa->p->d,
868                                 BN_num_bits(dsa->p),
869                                 (unsigned char *)dsa->q->d,
870                                 BN_num_bits(dsa->q),
871                                 (unsigned char *)dsa->g->d,
872                                 BN_num_bits(dsa->g),
873                                 (unsigned char *)dsa->pub_key->d,
874                                 BN_num_bits(dsa->pub_key),
875                                 (unsigned char *)sig->r->d,
876                                 BN_num_bits(sig->r),
877                                 (unsigned char *)sig->s->d,
878                                 BN_num_bits(sig->s), (unsigned char *)v.d,
879                                 &v_len) != 0) {
880        const DSA_METHOD *meth;
881        UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_REQUEST_FAILED);
882        p_UBSEC_ubsec_close(fd);
883
884        meth = DSA_OpenSSL();
885        to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
886
887        goto err;
888    }
889
890    p_UBSEC_ubsec_close(fd);
891
892    to_return = 1;
893 err:
894    BN_clear_free(&v);
895    return to_return;
896}
897#  endif
898
899#  ifndef OPENSSL_NO_DH
900static int ubsec_dh_compute_key(unsigned char *key, const BIGNUM *pub_key,
901                                DH *dh)
902{
903    int ret = -1, k_len, fd;
904
905    k_len = BN_num_bits(dh->p);
906
907    if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
908        const DH_METHOD *meth;
909        UBSECerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_UNIT_FAILURE);
910        meth = DH_OpenSSL();
911        ret = meth->compute_key(key, pub_key, dh);
912        goto err;
913    }
914
915    if (p_UBSEC_diffie_hellman_agree_ioctl(fd,
916                                           (unsigned char *)dh->priv_key->d,
917                                           BN_num_bits(dh->priv_key),
918                                           (unsigned char *)pub_key->d,
919                                           BN_num_bits(pub_key),
920                                           (unsigned char *)dh->p->d,
921                                           BN_num_bits(dh->p), key,
922                                           &k_len) != 0) {
923        /* Hardware's a no go, failover to software */
924        const DH_METHOD *meth;
925        UBSECerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_REQUEST_FAILED);
926        p_UBSEC_ubsec_close(fd);
927
928        meth = DH_OpenSSL();
929        ret = meth->compute_key(key, pub_key, dh);
930
931        goto err;
932    }
933
934    p_UBSEC_ubsec_close(fd);
935
936    ret = p_UBSEC_ubsec_bits_to_bytes(k_len);
937 err:
938    return ret;
939}
940
941static int ubsec_dh_generate_key(DH *dh)
942{
943    int ret = 0, random_bits = 0, pub_key_len = 0, priv_key_len = 0, fd;
944    BIGNUM *pub_key = NULL;
945    BIGNUM *priv_key = NULL;
946
947    /*
948     *  How many bits should Random x be? dh_key.c
949     *  sets the range from 0 to num_bits(modulus) ???
950     */
951
952    if (dh->priv_key == NULL) {
953        priv_key = BN_new();
954        if (priv_key == NULL)
955            goto err;
956        priv_key_len = BN_num_bits(dh->p);
957        if (bn_wexpand(priv_key, dh->p->top) == NULL)
958            goto err;
959        do
960            if (!BN_rand_range(priv_key, dh->p))
961                goto err;
962        while (BN_is_zero(priv_key)) ;
963        random_bits = BN_num_bits(priv_key);
964    } else {
965        priv_key = dh->priv_key;
966    }
967
968    if (dh->pub_key == NULL) {
969        pub_key = BN_new();
970        pub_key_len = BN_num_bits(dh->p);
971        if (bn_wexpand(pub_key, dh->p->top) == NULL)
972            goto err;
973        if (pub_key == NULL)
974            goto err;
975    } else {
976        pub_key = dh->pub_key;
977    }
978
979    if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
980        const DH_METHOD *meth;
981        UBSECerr(UBSEC_F_UBSEC_DH_GENERATE_KEY, UBSEC_R_UNIT_FAILURE);
982        meth = DH_OpenSSL();
983        ret = meth->generate_key(dh);
984        goto err;
985    }
986
987    if (p_UBSEC_diffie_hellman_generate_ioctl(fd,
988                                              (unsigned char *)priv_key->d,
989                                              &priv_key_len,
990                                              (unsigned char *)pub_key->d,
991                                              &pub_key_len,
992                                              (unsigned char *)dh->g->d,
993                                              BN_num_bits(dh->g),
994                                              (unsigned char *)dh->p->d,
995                                              BN_num_bits(dh->p), 0, 0,
996                                              random_bits) != 0) {
997        /* Hardware's a no go, failover to software */
998        const DH_METHOD *meth;
999
1000        UBSECerr(UBSEC_F_UBSEC_DH_GENERATE_KEY, UBSEC_R_REQUEST_FAILED);
1001        p_UBSEC_ubsec_close(fd);
1002
1003        meth = DH_OpenSSL();
1004        ret = meth->generate_key(dh);
1005
1006        goto err;
1007    }
1008
1009    p_UBSEC_ubsec_close(fd);
1010
1011    dh->pub_key = pub_key;
1012    dh->pub_key->top = (pub_key_len + BN_BITS2 - 1) / BN_BITS2;
1013    dh->priv_key = priv_key;
1014    dh->priv_key->top = (priv_key_len + BN_BITS2 - 1) / BN_BITS2;
1015
1016    ret = 1;
1017 err:
1018    return ret;
1019}
1020#  endif
1021
1022#  ifdef NOT_USED
1023static int ubsec_rand_bytes(unsigned char *buf, int num)
1024{
1025    int ret = 0, fd;
1026
1027    if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
1028        const RAND_METHOD *meth;
1029        UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_UNIT_FAILURE);
1030        num = p_UBSEC_ubsec_bits_to_bytes(num);
1031        meth = RAND_SSLeay();
1032        meth->seed(buf, num);
1033        ret = meth->bytes(buf, num);
1034        goto err;
1035    }
1036
1037    num *= 8;                   /* bytes to bits */
1038
1039    if (p_UBSEC_rng_ioctl(fd, UBSEC_RNG_DIRECT, buf, &num) != 0) {
1040        /* Hardware's a no go, failover to software */
1041        const RAND_METHOD *meth;
1042
1043        UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_REQUEST_FAILED);
1044        p_UBSEC_ubsec_close(fd);
1045
1046        num = p_UBSEC_ubsec_bits_to_bytes(num);
1047        meth = RAND_SSLeay();
1048        meth->seed(buf, num);
1049        ret = meth->bytes(buf, num);
1050
1051        goto err;
1052    }
1053
1054    p_UBSEC_ubsec_close(fd);
1055
1056    ret = 1;
1057 err:
1058    return (ret);
1059}
1060
1061static int ubsec_rand_status(void)
1062{
1063    return 0;
1064}
1065#  endif
1066
1067/*
1068 * This stuff is needed if this ENGINE is being compiled into a
1069 * self-contained shared-library.
1070 */
1071#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
1072static int bind_fn(ENGINE *e, const char *id)
1073{
1074    if (id && (strcmp(id, engine_ubsec_id) != 0))
1075        return 0;
1076    if (!bind_helper(e))
1077        return 0;
1078    return 1;
1079}
1080
1081IMPLEMENT_DYNAMIC_CHECK_FN()
1082    IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1083#  endif                        /* OPENSSL_NO_DYNAMIC_ENGINE */
1084# endif                         /* !OPENSSL_NO_HW_UBSEC */
1085#endif                          /* !OPENSSL_NO_HW */
1086