Coverage Report

Created: 2022-11-30 06:20

/src/openssl/engines/e_4758cca.c
Line
Count
Source (jump to first uncovered line)
1
/* Author: Maurice Gittens <maurice@gittens.nl>                       */
2
/* ====================================================================
3
 * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 *
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in
14
 *    the documentation and/or other materials provided with the
15
 *    distribution.
16
 *
17
 * 3. All advertising materials mentioning features or use of this
18
 *    software must display the following acknowledgment:
19
 *    "This product includes software developed by the OpenSSL Project
20
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21
 *
22
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23
 *    endorse or promote products derived from this software without
24
 *    prior written permission. For written permission, please contact
25
 *    licensing@OpenSSL.org.
26
 *
27
 * 5. Products derived from this software may not be called "OpenSSL"
28
 *    nor may "OpenSSL" appear in their names without prior written
29
 *    permission of the OpenSSL Project.
30
 *
31
 * 6. Redistributions of any form whatsoever must retain the following
32
 *    acknowledgment:
33
 *    "This product includes software developed by the OpenSSL Project
34
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35
 *
36
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47
 * OF THE POSSIBILITY OF SUCH DAMAGE.
48
 * ====================================================================
49
 *
50
 * This product includes cryptographic software written by Eric Young
51
 * (eay@cryptsoft.com).  This product includes software written by Tim
52
 * Hudson (tjh@cryptsoft.com).
53
 *
54
 */
55
56
#include <stdio.h>
57
#include <string.h>
58
#include <openssl/crypto.h>
59
#include <openssl/dso.h>
60
#include <openssl/x509.h>
61
#include <openssl/objects.h>
62
#include <openssl/engine.h>
63
#include <openssl/rand.h>
64
#ifndef OPENSSL_NO_RSA
65
# include <openssl/rsa.h>
66
#endif
67
#include <openssl/bn.h>
68
69
#ifndef OPENSSL_NO_HW
70
# ifndef OPENSSL_NO_HW_4758_CCA
71
72
#  ifdef FLAT_INC
73
#   include "hw_4758_cca.h"
74
#  else
75
#   include "vendor_defns/hw_4758_cca.h"
76
#  endif
77
78
#  include "e_4758cca_err.c"
79
80
static int ibm_4758_cca_destroy(ENGINE *e);
81
static int ibm_4758_cca_init(ENGINE *e);
82
static int ibm_4758_cca_finish(ENGINE *e);
83
static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p,
84
                             void (*f) (void));
85
86
/* rsa functions */
87
/* -------------*/
88
#  ifndef OPENSSL_NO_RSA
89
static int cca_rsa_pub_enc(int flen, const unsigned char *from,
90
                           unsigned char *to, RSA *rsa, int padding);
91
static int cca_rsa_priv_dec(int flen, const unsigned char *from,
92
                            unsigned char *to, RSA *rsa, int padding);
93
static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
94
                        unsigned char *sigret, unsigned int *siglen,
95
                        const RSA *rsa);
96
static int cca_rsa_verify(int dtype, const unsigned char *m,
97
                          unsigned int m_len, const unsigned char *sigbuf,
98
                          unsigned int siglen, const RSA *rsa);
99
100
/* utility functions */
101
/* ---------------------*/
102
static EVP_PKEY *ibm_4758_load_privkey(ENGINE *, const char *,
103
                                       UI_METHOD *ui_method,
104
                                       void *callback_data);
105
static EVP_PKEY *ibm_4758_load_pubkey(ENGINE *, const char *,
106
                                      UI_METHOD *ui_method,
107
                                      void *callback_data);
108
109
static int getModulusAndExponent(const unsigned char *token,
110
                                 long *exponentLength,
111
                                 unsigned char *exponent, long *modulusLength,
112
                                 long *modulusFieldLength,
113
                                 unsigned char *modulus);
114
#  endif
115
116
/* RAND number functions */
117
/* ---------------------*/
118
static int cca_get_random_bytes(unsigned char *, int);
119
static int cca_random_status(void);
120
121
#  ifndef OPENSSL_NO_RSA
122
static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
123
                        int idx, long argl, void *argp);
124
#  endif
125
126
/* Function pointers for CCA verbs */
127
/* -------------------------------*/
128
#  ifndef OPENSSL_NO_RSA
129
static F_KEYRECORDREAD keyRecordRead;
130
static F_DIGITALSIGNATUREGENERATE digitalSignatureGenerate;
131
static F_DIGITALSIGNATUREVERIFY digitalSignatureVerify;
132
static F_PUBLICKEYEXTRACT publicKeyExtract;
133
static F_PKAENCRYPT pkaEncrypt;
134
static F_PKADECRYPT pkaDecrypt;
135
#  endif
136
static F_RANDOMNUMBERGENERATE randomNumberGenerate;
137
138
/* static variables */
139
/* ----------------*/
140
static const char *CCA4758_LIB_NAME = NULL;
141
static const char *get_CCA4758_LIB_NAME(void)
142
18
{
143
18
    if (CCA4758_LIB_NAME)
144
0
        return CCA4758_LIB_NAME;
145
18
    return CCA_LIB_NAME;
146
18
}
147
148
static void free_CCA4758_LIB_NAME(void)
149
0
{
150
0
    if (CCA4758_LIB_NAME)
151
0
        OPENSSL_free((void *)CCA4758_LIB_NAME);
152
0
    CCA4758_LIB_NAME = NULL;
153
0
}
154
155
static long set_CCA4758_LIB_NAME(const char *name)
156
0
{
157
0
    free_CCA4758_LIB_NAME();
158
0
    return (((CCA4758_LIB_NAME = BUF_strdup(name)) != NULL) ? 1 : 0);
159
0
}
160
161
#  ifndef OPENSSL_NO_RSA
162
static const char *n_keyRecordRead = CSNDKRR;
163
static const char *n_digitalSignatureGenerate = CSNDDSG;
164
static const char *n_digitalSignatureVerify = CSNDDSV;
165
static const char *n_publicKeyExtract = CSNDPKX;
166
static const char *n_pkaEncrypt = CSNDPKE;
167
static const char *n_pkaDecrypt = CSNDPKD;
168
#  endif
169
static const char *n_randomNumberGenerate = CSNBRNG;
170
171
#  ifndef OPENSSL_NO_RSA
172
static int hndidx = -1;
173
#  endif
174
static DSO *dso = NULL;
175
176
/* openssl engine initialization structures */
177
/* ----------------------------------------*/
178
179
0
#  define CCA4758_CMD_SO_PATH             ENGINE_CMD_BASE
180
static const ENGINE_CMD_DEFN cca4758_cmd_defns[] = {
181
    {CCA4758_CMD_SO_PATH,
182
     "SO_PATH",
183
     "Specifies the path to the '4758cca' shared library",
184
     ENGINE_CMD_FLAG_STRING},
185
    {0, NULL, NULL, 0}
186
};
187
188
#  ifndef OPENSSL_NO_RSA
189
static RSA_METHOD ibm_4758_cca_rsa = {
190
    "IBM 4758 CCA RSA method",
191
    cca_rsa_pub_enc,
192
    NULL,
193
    NULL,
194
    cca_rsa_priv_dec,
195
    NULL,                       /* rsa_mod_exp, */
196
    NULL,                       /* mod_exp_mont, */
197
    NULL,                       /* init */
198
    NULL,                       /* finish */
199
    RSA_FLAG_SIGN_VER,          /* flags */
200
    NULL,                       /* app_data */
201
    cca_rsa_sign,               /* rsa_sign */
202
    cca_rsa_verify,             /* rsa_verify */
203
    NULL                        /* rsa_keygen */
204
};
205
#  endif
206
207
static RAND_METHOD ibm_4758_cca_rand = {
208
    /* "IBM 4758 RAND method", */
209
    NULL,                       /* seed */
210
    cca_get_random_bytes,       /* get random bytes from the card */
211
    NULL,                       /* cleanup */
212
    NULL,                       /* add */
213
    cca_get_random_bytes,       /* pseudo rand */
214
    cca_random_status,          /* status */
215
};
216
217
static const char *engine_4758_cca_id = "4758cca";
218
static const char *engine_4758_cca_name =
219
    "IBM 4758 CCA hardware engine support";
220
#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
221
/* Compatibility hack, the dynamic library uses this form in the path */
222
static const char *engine_4758_cca_id_alt = "4758_cca";
223
#  endif
224
225
/* engine implementation */
226
/* ---------------------*/
227
static int bind_helper(ENGINE *e)
228
19
{
229
19
    if (!ENGINE_set_id(e, engine_4758_cca_id) ||
230
19
        !ENGINE_set_name(e, engine_4758_cca_name) ||
231
19
#  ifndef OPENSSL_NO_RSA
232
19
        !ENGINE_set_RSA(e, &ibm_4758_cca_rsa) ||
233
19
#  endif
234
19
        !ENGINE_set_RAND(e, &ibm_4758_cca_rand) ||
235
19
        !ENGINE_set_destroy_function(e, ibm_4758_cca_destroy) ||
236
19
        !ENGINE_set_init_function(e, ibm_4758_cca_init) ||
237
19
        !ENGINE_set_finish_function(e, ibm_4758_cca_finish) ||
238
19
        !ENGINE_set_ctrl_function(e, ibm_4758_cca_ctrl) ||
239
19
#  ifndef OPENSSL_NO_RSA
240
19
        !ENGINE_set_load_privkey_function(e, ibm_4758_load_privkey) ||
241
19
        !ENGINE_set_load_pubkey_function(e, ibm_4758_load_pubkey) ||
242
19
#  endif
243
19
        !ENGINE_set_cmd_defns(e, cca4758_cmd_defns))
244
0
        return 0;
245
    /* Ensure the error handling is set up */
246
19
    ERR_load_CCA4758_strings();
247
19
    return 1;
248
19
}
249
250
#  ifdef OPENSSL_NO_DYNAMIC_ENGINE
251
static ENGINE *engine_4758_cca(void)
252
19
{
253
19
    ENGINE *ret = ENGINE_new();
254
19
    if (!ret)
255
0
        return NULL;
256
19
    if (!bind_helper(ret)) {
257
0
        ENGINE_free(ret);
258
0
        return NULL;
259
0
    }
260
19
    return ret;
261
19
}
262
263
void ENGINE_load_4758cca(void)
264
19
{
265
19
    ENGINE *e_4758 = engine_4758_cca();
266
19
    if (!e_4758)
267
0
        return;
268
19
    ENGINE_add(e_4758);
269
19
    ENGINE_free(e_4758);
270
19
    ERR_clear_error();
271
19
}
272
#  endif
273
274
static int ibm_4758_cca_destroy(ENGINE *e)
275
0
{
276
0
    ERR_unload_CCA4758_strings();
277
0
    free_CCA4758_LIB_NAME();
278
0
    return 1;
279
0
}
280
281
static int ibm_4758_cca_init(ENGINE *e)
282
18
{
283
18
    if (dso) {
284
0
        CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_ALREADY_LOADED);
285
0
        goto err;
286
0
    }
287
288
18
    dso = DSO_load(NULL, get_CCA4758_LIB_NAME(), NULL, 0);
289
18
    if (!dso) {
290
18
        CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_DSO_FAILURE);
291
18
        goto err;
292
18
    }
293
0
#  ifndef OPENSSL_NO_RSA
294
0
    if (!(keyRecordRead = (F_KEYRECORDREAD)
295
0
          DSO_bind_func(dso, n_keyRecordRead)) ||
296
0
        !(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
297
0
          DSO_bind_func(dso, n_randomNumberGenerate)) ||
298
0
        !(digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)
299
0
          DSO_bind_func(dso, n_digitalSignatureGenerate)) ||
300
0
        !(digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)
301
0
          DSO_bind_func(dso, n_digitalSignatureVerify)) ||
302
0
        !(publicKeyExtract = (F_PUBLICKEYEXTRACT)
303
0
          DSO_bind_func(dso, n_publicKeyExtract)) ||
304
0
        !(pkaEncrypt = (F_PKAENCRYPT)
305
0
          DSO_bind_func(dso, n_pkaEncrypt)) || !(pkaDecrypt = (F_PKADECRYPT)
306
0
                                                 DSO_bind_func(dso,
307
0
                                                               n_pkaDecrypt)))
308
0
    {
309
0
        CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_DSO_FAILURE);
310
0
        goto err;
311
0
    }
312
#  else
313
    if (!(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
314
          DSO_bind_func(dso, n_randomNumberGenerate))) {
315
        CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_DSO_FAILURE);
316
        goto err;
317
    }
318
#  endif
319
320
0
#  ifndef OPENSSL_NO_RSA
321
0
    hndidx = RSA_get_ex_new_index(0, "IBM 4758 CCA RSA key handle",
322
0
                                  NULL, NULL, cca_ex_free);
323
0
#  endif
324
325
0
    return 1;
326
18
 err:
327
18
    if (dso)
328
0
        DSO_free(dso);
329
18
    dso = NULL;
330
331
18
#  ifndef OPENSSL_NO_RSA
332
18
    keyRecordRead = (F_KEYRECORDREAD) 0;
333
18
    digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE) 0;
334
18
    digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
335
18
    publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
336
18
    pkaEncrypt = (F_PKAENCRYPT) 0;
337
18
    pkaDecrypt = (F_PKADECRYPT) 0;
338
18
#  endif
339
18
    randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0;
340
18
    return 0;
341
0
}
342
343
static int ibm_4758_cca_finish(ENGINE *e)
344
0
{
345
0
    free_CCA4758_LIB_NAME();
346
0
    if (!dso) {
347
0
        CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH, CCA4758_R_NOT_LOADED);
348
0
        return 0;
349
0
    }
350
0
    if (!DSO_free(dso)) {
351
0
        CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH, CCA4758_R_UNIT_FAILURE);
352
0
        return 0;
353
0
    }
354
0
    dso = NULL;
355
0
#  ifndef OPENSSL_NO_RSA
356
0
    keyRecordRead = (F_KEYRECORDREAD) 0;
357
0
    randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0;
358
0
    digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE) 0;
359
0
    digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
360
0
    publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
361
0
    pkaEncrypt = (F_PKAENCRYPT) 0;
362
0
    pkaDecrypt = (F_PKADECRYPT) 0;
363
0
#  endif
364
0
    randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0;
365
0
    return 1;
366
0
}
367
368
static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p,
369
                             void (*f) (void))
370
0
{
371
0
    int initialised = ((dso == NULL) ? 0 : 1);
372
0
    switch (cmd) {
373
0
    case CCA4758_CMD_SO_PATH:
374
0
        if (p == NULL) {
375
0
            CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
376
0
                       ERR_R_PASSED_NULL_PARAMETER);
377
0
            return 0;
378
0
        }
379
0
        if (initialised) {
380
0
            CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL, CCA4758_R_ALREADY_LOADED);
381
0
            return 0;
382
0
        }
383
0
        return set_CCA4758_LIB_NAME((const char *)p);
384
0
    default:
385
0
        break;
386
0
    }
387
0
    CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
388
0
               CCA4758_R_COMMAND_NOT_IMPLEMENTED);
389
0
    return 0;
390
0
}
391
392
#  ifndef OPENSSL_NO_RSA
393
394
0
#   define MAX_CCA_PKA_TOKEN_SIZE 2500
395
396
static EVP_PKEY *ibm_4758_load_privkey(ENGINE *e, const char *key_id,
397
                                       UI_METHOD *ui_method,
398
                                       void *callback_data)
399
0
{
400
0
    RSA *rtmp = NULL;
401
0
    EVP_PKEY *res = NULL;
402
0
    unsigned char *keyToken = NULL;
403
0
    unsigned char pubKeyToken[MAX_CCA_PKA_TOKEN_SIZE];
404
0
    long pubKeyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
405
0
    long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
406
0
    long returnCode;
407
0
    long reasonCode;
408
0
    long exitDataLength = 0;
409
0
    long ruleArrayLength = 0;
410
0
    unsigned char exitData[8];
411
0
    unsigned char ruleArray[8];
412
0
    unsigned char keyLabel[64];
413
0
    unsigned long keyLabelLength = strlen(key_id);
414
0
    unsigned char modulus[256];
415
0
    long modulusFieldLength = sizeof(modulus);
416
0
    long modulusLength = 0;
417
0
    unsigned char exponent[256];
418
0
    long exponentLength = sizeof(exponent);
419
420
0
    if (keyLabelLength > sizeof(keyLabel)) {
421
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
422
0
                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
423
0
        return NULL;
424
0
    }
425
426
0
    memset(keyLabel, ' ', sizeof(keyLabel));
427
0
    memcpy(keyLabel, key_id, keyLabelLength);
428
429
0
    keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
430
0
    if (!keyToken) {
431
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
432
0
        goto err;
433
0
    }
434
435
0
    keyRecordRead(&returnCode, &reasonCode, &exitDataLength,
436
0
                  exitData, &ruleArrayLength, ruleArray, keyLabel,
437
0
                  &keyTokenLength, keyToken + sizeof(long));
438
439
0
    if (returnCode) {
440
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
441
0
                   CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
442
0
        goto err;
443
0
    }
444
445
0
    publicKeyExtract(&returnCode, &reasonCode, &exitDataLength,
446
0
                     exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
447
0
                     keyToken + sizeof(long), &pubKeyTokenLength,
448
0
                     pubKeyToken);
449
450
0
    if (returnCode) {
451
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
452
0
                   CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
453
0
        goto err;
454
0
    }
455
456
0
    if (!getModulusAndExponent(pubKeyToken, &exponentLength,
457
0
                               exponent, &modulusLength, &modulusFieldLength,
458
0
                               modulus)) {
459
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
460
0
                   CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
461
0
        goto err;
462
0
    }
463
464
0
    (*(long *)keyToken) = keyTokenLength;
465
0
    rtmp = RSA_new_method(e);
466
0
    if (rtmp == NULL) {
467
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
468
0
        goto err;
469
0
    }
470
0
    RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
471
472
0
    rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
473
0
    rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
474
0
    rtmp->flags |= RSA_FLAG_EXT_PKEY;
475
476
0
    res = EVP_PKEY_new();
477
0
    EVP_PKEY_assign_RSA(res, rtmp);
478
479
0
    return res;
480
0
 err:
481
0
    if (keyToken)
482
0
        OPENSSL_free(keyToken);
483
0
    return NULL;
484
0
}
485
486
static EVP_PKEY *ibm_4758_load_pubkey(ENGINE *e, const char *key_id,
487
                                      UI_METHOD *ui_method,
488
                                      void *callback_data)
489
0
{
490
0
    RSA *rtmp = NULL;
491
0
    EVP_PKEY *res = NULL;
492
0
    unsigned char *keyToken = NULL;
493
0
    long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
494
0
    long returnCode;
495
0
    long reasonCode;
496
0
    long exitDataLength = 0;
497
0
    long ruleArrayLength = 0;
498
0
    unsigned char exitData[8];
499
0
    unsigned char ruleArray[8];
500
0
    unsigned char keyLabel[64];
501
0
    unsigned long keyLabelLength = strlen(key_id);
502
0
    unsigned char modulus[512];
503
0
    long modulusFieldLength = sizeof(modulus);
504
0
    long modulusLength = 0;
505
0
    unsigned char exponent[512];
506
0
    long exponentLength = sizeof(exponent);
507
508
0
    if (keyLabelLength > sizeof(keyLabel)) {
509
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
510
0
                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
511
0
        return NULL;
512
0
    }
513
514
0
    memset(keyLabel, ' ', sizeof(keyLabel));
515
0
    memcpy(keyLabel, key_id, keyLabelLength);
516
517
0
    keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
518
0
    if (!keyToken) {
519
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
520
0
        goto err;
521
0
    }
522
523
0
    keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData,
524
0
                  &ruleArrayLength, ruleArray, keyLabel, &keyTokenLength,
525
0
                  keyToken + sizeof(long));
526
527
0
    if (returnCode) {
528
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
529
0
        goto err;
530
0
    }
531
532
0
    if (!getModulusAndExponent(keyToken + sizeof(long), &exponentLength,
533
0
                               exponent, &modulusLength, &modulusFieldLength,
534
0
                               modulus)) {
535
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
536
0
                   CCA4758_R_FAILED_LOADING_PUBLIC_KEY);
537
0
        goto err;
538
0
    }
539
540
0
    (*(long *)keyToken) = keyTokenLength;
541
0
    rtmp = RSA_new_method(e);
542
0
    if (rtmp == NULL) {
543
0
        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
544
0
        goto err;
545
0
    }
546
0
    RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
547
0
    rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
548
0
    rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
549
0
    rtmp->flags |= RSA_FLAG_EXT_PKEY;
550
0
    res = EVP_PKEY_new();
551
0
    EVP_PKEY_assign_RSA(res, rtmp);
552
553
0
    return res;
554
0
 err:
555
0
    if (keyToken)
556
0
        OPENSSL_free(keyToken);
557
0
    return NULL;
558
0
}
559
560
static int cca_rsa_pub_enc(int flen, const unsigned char *from,
561
                           unsigned char *to, RSA *rsa, int padding)
562
0
{
563
0
    long returnCode;
564
0
    long reasonCode;
565
0
    long lflen = flen;
566
0
    long exitDataLength = 0;
567
0
    unsigned char exitData[8];
568
0
    long ruleArrayLength = 1;
569
0
    unsigned char ruleArray[8] = "PKCS-1.2";
570
0
    long dataStructureLength = 0;
571
0
    unsigned char dataStructure[8];
572
0
    long outputLength = RSA_size(rsa);
573
0
    long keyTokenLength;
574
0
    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
575
576
0
    keyTokenLength = *(long *)keyToken;
577
0
    keyToken += sizeof(long);
578
579
0
    pkaEncrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
580
0
               &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from,
581
0
               &dataStructureLength, dataStructure, &keyTokenLength,
582
0
               keyToken, &outputLength, to);
583
584
0
    if (returnCode || reasonCode)
585
0
        return -(returnCode << 16 | reasonCode);
586
0
    return outputLength;
587
0
}
588
589
static int cca_rsa_priv_dec(int flen, const unsigned char *from,
590
                            unsigned char *to, RSA *rsa, int padding)
591
0
{
592
0
    long returnCode;
593
0
    long reasonCode;
594
0
    long lflen = flen;
595
0
    long exitDataLength = 0;
596
0
    unsigned char exitData[8];
597
0
    long ruleArrayLength = 1;
598
0
    unsigned char ruleArray[8] = "PKCS-1.2";
599
0
    long dataStructureLength = 0;
600
0
    unsigned char dataStructure[8];
601
0
    long outputLength = RSA_size(rsa);
602
0
    long keyTokenLength;
603
0
    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
604
605
0
    keyTokenLength = *(long *)keyToken;
606
0
    keyToken += sizeof(long);
607
608
0
    pkaDecrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
609
0
               &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from,
610
0
               &dataStructureLength, dataStructure, &keyTokenLength,
611
0
               keyToken, &outputLength, to);
612
613
0
    return (returnCode | reasonCode) ? 0 : 1;
614
0
}
615
616
0
#   define SSL_SIG_LEN 36
617
618
static int cca_rsa_verify(int type, const unsigned char *m,
619
                          unsigned int m_len, const unsigned char *sigbuf,
620
                          unsigned int siglen, const RSA *rsa)
621
0
{
622
0
    long returnCode;
623
0
    long reasonCode;
624
0
    long lsiglen = siglen;
625
0
    long exitDataLength = 0;
626
0
    unsigned char exitData[8];
627
0
    long ruleArrayLength = 1;
628
0
    unsigned char ruleArray[8] = "PKCS-1.1";
629
0
    long keyTokenLength;
630
0
    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
631
0
    long length = SSL_SIG_LEN;
632
0
    long keyLength;
633
0
    unsigned char *hashBuffer = NULL;
634
0
    X509_SIG sig;
635
0
    ASN1_TYPE parameter;
636
0
    X509_ALGOR algorithm;
637
0
    ASN1_OCTET_STRING digest;
638
639
0
    keyTokenLength = *(long *)keyToken;
640
0
    keyToken += sizeof(long);
641
642
0
    if (type == NID_md5 || type == NID_sha1) {
643
0
        sig.algor = &algorithm;
644
0
        algorithm.algorithm = OBJ_nid2obj(type);
645
646
0
        if (!algorithm.algorithm) {
647
0
            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
648
0
                       CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
649
0
            return 0;
650
0
        }
651
652
0
        if (!algorithm.algorithm->length) {
653
0
            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
654
0
                       CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
655
0
            return 0;
656
0
        }
657
658
0
        parameter.type = V_ASN1_NULL;
659
0
        parameter.value.ptr = NULL;
660
0
        algorithm.parameter = &parameter;
661
662
0
        sig.digest = &digest;
663
0
        sig.digest->data = (unsigned char *)m;
664
0
        sig.digest->length = m_len;
665
666
0
        length = i2d_X509_SIG(&sig, NULL);
667
0
    }
668
669
0
    keyLength = RSA_size(rsa);
670
671
0
    if (length - RSA_PKCS1_PADDING > keyLength) {
672
0
        CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
673
0
                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
674
0
        return 0;
675
0
    }
676
677
0
    switch (type) {
678
0
    case NID_md5_sha1:
679
0
        if (m_len != SSL_SIG_LEN) {
680
0
            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
681
0
                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
682
0
            return 0;
683
0
        }
684
685
0
        hashBuffer = (unsigned char *)m;
686
0
        length = m_len;
687
0
        break;
688
0
    case NID_md5:
689
0
        {
690
0
            unsigned char *ptr;
691
0
            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
692
0
            if (!hashBuffer) {
693
0
                CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
694
0
                return 0;
695
0
            }
696
697
0
            i2d_X509_SIG(&sig, &ptr);
698
0
        }
699
0
        break;
700
0
    case NID_sha1:
701
0
        {
702
0
            unsigned char *ptr;
703
0
            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
704
0
            if (!hashBuffer) {
705
0
                CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
706
0
                return 0;
707
0
            }
708
0
            i2d_X509_SIG(&sig, &ptr);
709
0
        }
710
0
        break;
711
0
    default:
712
0
        return 0;
713
0
    }
714
715
0
    digitalSignatureVerify(&returnCode, &reasonCode, &exitDataLength,
716
0
                           exitData, &ruleArrayLength, ruleArray,
717
0
                           &keyTokenLength, keyToken, &length, hashBuffer,
718
0
                           &lsiglen, (unsigned char *)sigbuf);
719
720
0
    if (type == NID_sha1 || type == NID_md5) {
721
0
        OPENSSL_cleanse(hashBuffer, keyLength + 1);
722
0
        OPENSSL_free(hashBuffer);
723
0
    }
724
725
0
    return ((returnCode || reasonCode) ? 0 : 1);
726
0
}
727
728
0
#   define SSL_SIG_LEN 36
729
730
static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
731
                        unsigned char *sigret, unsigned int *siglen,
732
                        const RSA *rsa)
733
0
{
734
0
    long returnCode;
735
0
    long reasonCode;
736
0
    long exitDataLength = 0;
737
0
    unsigned char exitData[8];
738
0
    long ruleArrayLength = 1;
739
0
    unsigned char ruleArray[8] = "PKCS-1.1";
740
0
    long outputLength = 256;
741
0
    long outputBitLength;
742
0
    long keyTokenLength;
743
0
    unsigned char *hashBuffer = NULL;
744
0
    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
745
0
    long length = SSL_SIG_LEN;
746
0
    long keyLength;
747
0
    X509_SIG sig;
748
0
    ASN1_TYPE parameter;
749
0
    X509_ALGOR algorithm;
750
0
    ASN1_OCTET_STRING digest;
751
752
0
    keyTokenLength = *(long *)keyToken;
753
0
    keyToken += sizeof(long);
754
755
0
    if (type == NID_md5 || type == NID_sha1) {
756
0
        sig.algor = &algorithm;
757
0
        algorithm.algorithm = OBJ_nid2obj(type);
758
759
0
        if (!algorithm.algorithm) {
760
0
            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
761
0
                       CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
762
0
            return 0;
763
0
        }
764
765
0
        if (!algorithm.algorithm->length) {
766
0
            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
767
0
                       CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
768
0
            return 0;
769
0
        }
770
771
0
        parameter.type = V_ASN1_NULL;
772
0
        parameter.value.ptr = NULL;
773
0
        algorithm.parameter = &parameter;
774
775
0
        sig.digest = &digest;
776
0
        sig.digest->data = (unsigned char *)m;
777
0
        sig.digest->length = m_len;
778
779
0
        length = i2d_X509_SIG(&sig, NULL);
780
0
    }
781
782
0
    keyLength = RSA_size(rsa);
783
784
0
    if (length - RSA_PKCS1_PADDING > keyLength) {
785
0
        CCA4758err(CCA4758_F_CCA_RSA_SIGN,
786
0
                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
787
0
        return 0;
788
0
    }
789
790
0
    switch (type) {
791
0
    case NID_md5_sha1:
792
0
        if (m_len != SSL_SIG_LEN) {
793
0
            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
794
0
                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
795
0
            return 0;
796
0
        }
797
0
        hashBuffer = (unsigned char *)m;
798
0
        length = m_len;
799
0
        break;
800
0
    case NID_md5:
801
0
        {
802
0
            unsigned char *ptr;
803
0
            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
804
0
            if (!hashBuffer) {
805
0
                CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE);
806
0
                return 0;
807
0
            }
808
0
            i2d_X509_SIG(&sig, &ptr);
809
0
        }
810
0
        break;
811
0
    case NID_sha1:
812
0
        {
813
0
            unsigned char *ptr;
814
0
            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
815
0
            if (!hashBuffer) {
816
0
                CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE);
817
0
                return 0;
818
0
            }
819
0
            i2d_X509_SIG(&sig, &ptr);
820
0
        }
821
0
        break;
822
0
    default:
823
0
        return 0;
824
0
    }
825
826
0
    digitalSignatureGenerate(&returnCode, &reasonCode, &exitDataLength,
827
0
                             exitData, &ruleArrayLength, ruleArray,
828
0
                             &keyTokenLength, keyToken, &length, hashBuffer,
829
0
                             &outputLength, &outputBitLength, sigret);
830
831
0
    if (type == NID_sha1 || type == NID_md5) {
832
0
        OPENSSL_cleanse(hashBuffer, keyLength + 1);
833
0
        OPENSSL_free(hashBuffer);
834
0
    }
835
836
0
    *siglen = outputLength;
837
838
0
    return ((returnCode || reasonCode) ? 0 : 1);
839
0
}
840
841
static int getModulusAndExponent(const unsigned char *token,
842
                                 long *exponentLength,
843
                                 unsigned char *exponent, long *modulusLength,
844
                                 long *modulusFieldLength,
845
                                 unsigned char *modulus)
846
0
{
847
0
    unsigned long len;
848
849
0
    if (*token++ != (char)0x1E) /* internal PKA token? */
850
0
        return 0;
851
852
0
    if (*token++)               /* token version must be zero */
853
0
        return 0;
854
855
0
    len = *token++;
856
0
    len = len << 8;
857
0
    len |= (unsigned char)*token++;
858
859
0
    token += 4;                 /* skip reserved bytes */
860
861
0
    if (*token++ == (char)0x04) {
862
0
        if (*token++)           /* token version must be zero */
863
0
            return 0;
864
865
0
        len = *token++;
866
0
        len = len << 8;
867
0
        len |= (unsigned char)*token++;
868
869
0
        token += 2;             /* skip reserved section */
870
871
0
        len = *token++;
872
0
        len = len << 8;
873
0
        len |= (unsigned char)*token++;
874
875
0
        *exponentLength = len;
876
877
0
        len = *token++;
878
0
        len = len << 8;
879
0
        len |= (unsigned char)*token++;
880
881
0
        *modulusLength = len;
882
883
0
        len = *token++;
884
0
        len = len << 8;
885
0
        len |= (unsigned char)*token++;
886
887
0
        *modulusFieldLength = len;
888
889
0
        memcpy(exponent, token, *exponentLength);
890
0
        token += *exponentLength;
891
892
0
        memcpy(modulus, token, *modulusFieldLength);
893
0
        return 1;
894
0
    }
895
0
    return 0;
896
0
}
897
898
#  endif                        /* OPENSSL_NO_RSA */
899
900
static int cca_random_status(void)
901
0
{
902
0
    return 1;
903
0
}
904
905
static int cca_get_random_bytes(unsigned char *buf, int num)
906
0
{
907
0
    long ret_code;
908
0
    long reason_code;
909
0
    long exit_data_length;
910
0
    unsigned char exit_data[4];
911
0
    unsigned char form[] = "RANDOM  ";
912
0
    unsigned char rand_buf[8];
913
914
0
    while (num >= (int)sizeof(rand_buf)) {
915
0
        randomNumberGenerate(&ret_code, &reason_code, &exit_data_length,
916
0
                             exit_data, form, rand_buf);
917
0
        if (ret_code)
918
0
            return 0;
919
0
        num -= sizeof(rand_buf);
920
0
        memcpy(buf, rand_buf, sizeof(rand_buf));
921
0
        buf += sizeof(rand_buf);
922
0
    }
923
924
0
    if (num) {
925
0
        randomNumberGenerate(&ret_code, &reason_code, NULL, NULL,
926
0
                             form, rand_buf);
927
0
        if (ret_code)
928
0
            return 0;
929
0
        memcpy(buf, rand_buf, num);
930
0
    }
931
932
0
    return 1;
933
0
}
934
935
#  ifndef OPENSSL_NO_RSA
936
static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, int idx,
937
                        long argl, void *argp)
938
0
{
939
0
    if (item)
940
0
        OPENSSL_free(item);
941
0
}
942
#  endif
943
944
/* Goo to handle building as a dynamic engine */
945
#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
946
static int bind_fn(ENGINE *e, const char *id)
947
{
948
    if (id && (strcmp(id, engine_4758_cca_id) != 0) &&
949
        (strcmp(id, engine_4758_cca_id_alt) != 0))
950
        return 0;
951
    if (!bind_helper(e))
952
        return 0;
953
    return 1;
954
}
955
956
IMPLEMENT_DYNAMIC_CHECK_FN()
957
    IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
958
#  endif                        /* OPENSSL_NO_DYNAMIC_ENGINE */
959
# endif                         /* !OPENSSL_NO_HW_4758_CCA */
960
#endif                          /* !OPENSSL_NO_HW */