1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
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, void (*f)(void));
84:
85:
86:
87: #ifndef OPENSSL_NO_RSA
88: static int cca_rsa_pub_enc(int flen, const unsigned char *from,
89: unsigned char *to, RSA *rsa,int padding);
90: static int cca_rsa_priv_dec(int flen, const unsigned char *from,
91: unsigned char *to, RSA *rsa,int padding);
92: static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
93: unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
94: static int cca_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
95: unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
96:
97:
98:
99: static EVP_PKEY *ibm_4758_load_privkey(ENGINE*, const char*,
100: UI_METHOD *ui_method, void *callback_data);
101: static EVP_PKEY *ibm_4758_load_pubkey(ENGINE*, const char*,
102: UI_METHOD *ui_method, void *callback_data);
103:
104: static int getModulusAndExponent(const unsigned char *token, long *exponentLength,
105: unsigned char *exponent, long *modulusLength,
106: long *modulusFieldLength, unsigned char *modulus);
107: #endif
108:
109:
110:
111: static int cca_get_random_bytes(unsigned char*, int );
112: static int cca_random_status(void);
113:
114: #ifndef OPENSSL_NO_RSA
115: static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
116: int idx,long argl, void *argp);
117: #endif
118:
119:
120:
121: #ifndef OPENSSL_NO_RSA
122: static F_KEYRECORDREAD keyRecordRead;
123: static F_DIGITALSIGNATUREGENERATE digitalSignatureGenerate;
124: static F_DIGITALSIGNATUREVERIFY digitalSignatureVerify;
125: static F_PUBLICKEYEXTRACT publicKeyExtract;
126: static F_PKAENCRYPT pkaEncrypt;
127: static F_PKADECRYPT pkaDecrypt;
128: #endif
129: static F_RANDOMNUMBERGENERATE randomNumberGenerate;
130:
131:
132:
133: static const char *CCA4758_LIB_NAME = NULL;
134: static const char *get_CCA4758_LIB_NAME(void)
135: {
136: if(CCA4758_LIB_NAME)
137: return CCA4758_LIB_NAME;
138: return CCA_LIB_NAME;
139: }
140: static void free_CCA4758_LIB_NAME(void)
141: {
142: if(CCA4758_LIB_NAME)
143: OPENSSL_free((void*)CCA4758_LIB_NAME);
144: CCA4758_LIB_NAME = NULL;
145: }
146: static long set_CCA4758_LIB_NAME(const char *name)
147: {
148: free_CCA4758_LIB_NAME();
149: return (((CCA4758_LIB_NAME = BUF_strdup(name)) != NULL) ? 1 : 0);
150: }
151: #ifndef OPENSSL_NO_RSA
152: static const char* n_keyRecordRead = CSNDKRR;
153: static const char* n_digitalSignatureGenerate = CSNDDSG;
154: static const char* n_digitalSignatureVerify = CSNDDSV;
155: static const char* n_publicKeyExtract = CSNDPKX;
156: static const char* n_pkaEncrypt = CSNDPKE;
157: static const char* n_pkaDecrypt = CSNDPKD;
158: #endif
159: static const char* n_randomNumberGenerate = CSNBRNG;
160:
161: #ifndef OPENSSL_NO_RSA
162: static int hndidx = -1;
163: #endif
164: static DSO *dso = NULL;
165:
166:
167:
168:
169: #define CCA4758_CMD_SO_PATH ENGINE_CMD_BASE
170: static const ENGINE_CMD_DEFN cca4758_cmd_defns[] = {
171: {CCA4758_CMD_SO_PATH,
172: "SO_PATH",
173: "Specifies the path to the '4758cca' shared library",
174: ENGINE_CMD_FLAG_STRING},
175: {0, NULL, NULL, 0}
176: };
177:
178: #ifndef OPENSSL_NO_RSA
179: static RSA_METHOD ibm_4758_cca_rsa =
180: {
181: "IBM 4758 CCA RSA method",
182: cca_rsa_pub_enc,
183: NULL,
184: NULL,
185: cca_rsa_priv_dec,
186: NULL,
187: NULL,
188: NULL,
189: NULL,
190: RSA_FLAG_SIGN_VER,
191: NULL,
192: cca_rsa_sign,
193: cca_rsa_verify,
194: NULL
195: };
196: #endif
197:
198: static RAND_METHOD ibm_4758_cca_rand =
199: {
200:
201: NULL,
202: cca_get_random_bytes,
203: NULL,
204: NULL,
205: cca_get_random_bytes,
206: cca_random_status,
207: };
208:
209: static const char *engine_4758_cca_id = "4758cca";
210: static const char *engine_4758_cca_name = "IBM 4758 CCA hardware engine support";
211: #ifndef OPENSSL_NO_DYNAMIC_ENGINE
212:
213: static const char *engine_4758_cca_id_alt = "4758_cca";
214: #endif
215:
216:
217:
218: static int bind_helper(ENGINE *e)
219: {
220: if(!ENGINE_set_id(e, engine_4758_cca_id) ||
221: !ENGINE_set_name(e, engine_4758_cca_name) ||
222: #ifndef OPENSSL_NO_RSA
223: !ENGINE_set_RSA(e, &ibm_4758_cca_rsa) ||
224: #endif
225: !ENGINE_set_RAND(e, &ibm_4758_cca_rand) ||
226: !ENGINE_set_destroy_function(e, ibm_4758_cca_destroy) ||
227: !ENGINE_set_init_function(e, ibm_4758_cca_init) ||
228: !ENGINE_set_finish_function(e, ibm_4758_cca_finish) ||
229: !ENGINE_set_ctrl_function(e, ibm_4758_cca_ctrl) ||
230: #ifndef OPENSSL_NO_RSA
231: !ENGINE_set_load_privkey_function(e, ibm_4758_load_privkey) ||
232: !ENGINE_set_load_pubkey_function(e, ibm_4758_load_pubkey) ||
233: #endif
234: !ENGINE_set_cmd_defns(e, cca4758_cmd_defns))
235: return 0;
236:
237: ERR_load_CCA4758_strings();
238: return 1;
239: }
240:
241: #ifdef OPENSSL_NO_DYNAMIC_ENGINE
242: static ENGINE *engine_4758_cca(void)
243: {
244: ENGINE *ret = ENGINE_new();
245: if(!ret)
246: return NULL;
247: if(!bind_helper(ret))
248: {
249: ENGINE_free(ret);
250: return NULL;
251: }
252: return ret;
253: }
254:
255: void ENGINE_load_4758cca(void)
256: {
257: ENGINE *e_4758 = engine_4758_cca();
258: if (!e_4758) return;
259: ENGINE_add(e_4758);
260: ENGINE_free(e_4758);
261: ERR_clear_error();
262: }
263: #endif
264:
265: static int ibm_4758_cca_destroy(ENGINE *e)
266: {
267: ERR_unload_CCA4758_strings();
268: free_CCA4758_LIB_NAME();
269: return 1;
270: }
271:
272: static int ibm_4758_cca_init(ENGINE *e)
273: {
274: if(dso)
275: {
276: CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_ALREADY_LOADED);
277: goto err;
278: }
279:
280: dso = DSO_load(NULL, get_CCA4758_LIB_NAME(), NULL, 0);
281: if(!dso)
282: {
283: CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
284: goto err;
285: }
286:
287: #ifndef OPENSSL_NO_RSA
288: if(!(keyRecordRead = (F_KEYRECORDREAD)
289: DSO_bind_func(dso, n_keyRecordRead)) ||
290: !(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
291: DSO_bind_func(dso, n_randomNumberGenerate)) ||
292: !(digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)
293: DSO_bind_func(dso, n_digitalSignatureGenerate)) ||
294: !(digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)
295: DSO_bind_func(dso, n_digitalSignatureVerify)) ||
296: !(publicKeyExtract = (F_PUBLICKEYEXTRACT)
297: DSO_bind_func(dso, n_publicKeyExtract)) ||
298: !(pkaEncrypt = (F_PKAENCRYPT)
299: DSO_bind_func(dso, n_pkaEncrypt)) ||
300: !(pkaDecrypt = (F_PKADECRYPT)
301: DSO_bind_func(dso, n_pkaDecrypt)))
302: {
303: CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
304: goto err;
305: }
306: #else
307: if(!(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
308: DSO_bind_func(dso, n_randomNumberGenerate)))
309: {
310: CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
311: goto err;
312: }
313: #endif
314:
315: #ifndef OPENSSL_NO_RSA
316: hndidx = RSA_get_ex_new_index(0, "IBM 4758 CCA RSA key handle",
317: NULL, NULL, cca_ex_free);
318: #endif
319:
320: return 1;
321: err:
322: if(dso)
323: DSO_free(dso);
324: dso = NULL;
325:
326: #ifndef OPENSSL_NO_RSA
327: keyRecordRead = (F_KEYRECORDREAD)0;
328: digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)0;
329: digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
330: publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
331: pkaEncrypt = (F_PKAENCRYPT)0;
332: pkaDecrypt = (F_PKADECRYPT)0;
333: #endif
334: randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
335: return 0;
336: }
337:
338: static int ibm_4758_cca_finish(ENGINE *e)
339: {
340: free_CCA4758_LIB_NAME();
341: if(!dso)
342: {
343: CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
344: CCA4758_R_NOT_LOADED);
345: return 0;
346: }
347: if(!DSO_free(dso))
348: {
349: CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
350: CCA4758_R_UNIT_FAILURE);
351: return 0;
352: }
353: dso = NULL;
354: #ifndef OPENSSL_NO_RSA
355: keyRecordRead = (F_KEYRECORDREAD)0;
356: randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
357: digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)0;
358: digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
359: publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
360: pkaEncrypt = (F_PKAENCRYPT)0;
361: pkaDecrypt = (F_PKADECRYPT)0;
362: #endif
363: randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
364: return 1;
365: }
366:
367: static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
368: {
369: int initialised = ((dso == NULL) ? 0 : 1);
370: switch(cmd)
371: {
372: case CCA4758_CMD_SO_PATH:
373: if(p == NULL)
374: {
375: CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
376: ERR_R_PASSED_NULL_PARAMETER);
377: return 0;
378: }
379: if(initialised)
380: {
381: CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
382: CCA4758_R_ALREADY_LOADED);
383: return 0;
384: }
385: return set_CCA4758_LIB_NAME((const char *)p);
386: default:
387: break;
388: }
389: CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
390: CCA4758_R_COMMAND_NOT_IMPLEMENTED);
391: return 0;
392: }
393:
394: #ifndef OPENSSL_NO_RSA
395:
396: #define MAX_CCA_PKA_TOKEN_SIZE 2500
397:
398: static EVP_PKEY *ibm_4758_load_privkey(ENGINE* e, const char* key_id,
399: UI_METHOD *ui_method, void *callback_data)
400: {
401: RSA *rtmp = NULL;
402: EVP_PKEY *res = NULL;
403: unsigned char* keyToken = NULL;
404: unsigned char pubKeyToken[MAX_CCA_PKA_TOKEN_SIZE];
405: long pubKeyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
406: long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
407: long returnCode;
408: long reasonCode;
409: long exitDataLength = 0;
410: long ruleArrayLength = 0;
411: unsigned char exitData[8];
412: unsigned char ruleArray[8];
413: unsigned char keyLabel[64];
414: unsigned long keyLabelLength = strlen(key_id);
415: unsigned char modulus[256];
416: long modulusFieldLength = sizeof(modulus);
417: long modulusLength = 0;
418: unsigned char exponent[256];
419: long exponentLength = sizeof(exponent);
420:
421: if (keyLabelLength > sizeof(keyLabel))
422: {
423: CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
424: CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
425: return NULL;
426: }
427:
428: memset(keyLabel,' ', sizeof(keyLabel));
429: memcpy(keyLabel, key_id, keyLabelLength);
430:
431: keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
432: if (!keyToken)
433: {
434: CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
435: ERR_R_MALLOC_FAILURE);
436: goto err;
437: }
438:
439: keyRecordRead(&returnCode, &reasonCode, &exitDataLength,
440: exitData, &ruleArrayLength, ruleArray, keyLabel,
441: &keyTokenLength, keyToken+sizeof(long));
442:
443: if (returnCode)
444: {
445: CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
446: CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
447: goto err;
448: }
449:
450: publicKeyExtract(&returnCode, &reasonCode, &exitDataLength,
451: exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
452: keyToken+sizeof(long), &pubKeyTokenLength, pubKeyToken);
453:
454: if (returnCode)
455: {
456: CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
457: CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
458: goto err;
459: }
460:
461: if (!getModulusAndExponent(pubKeyToken, &exponentLength,
462: exponent, &modulusLength, &modulusFieldLength,
463: modulus))
464: {
465: CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
466: CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
467: goto err;
468: }
469:
470: (*(long*)keyToken) = keyTokenLength;
471: rtmp = RSA_new_method(e);
472: RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
473:
474: rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
475: rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
476: rtmp->flags |= RSA_FLAG_EXT_PKEY;
477:
478: res = EVP_PKEY_new();
479: EVP_PKEY_assign_RSA(res, rtmp);
480:
481: return res;
482: err:
483: if (keyToken)
484: OPENSSL_free(keyToken);
485: if (res)
486: EVP_PKEY_free(res);
487: if (rtmp)
488: RSA_free(rtmp);
489: return NULL;
490: }
491:
492: static EVP_PKEY *ibm_4758_load_pubkey(ENGINE* e, const char* key_id,
493: UI_METHOD *ui_method, void *callback_data)
494: {
495: RSA *rtmp = NULL;
496: EVP_PKEY *res = NULL;
497: unsigned char* keyToken = NULL;
498: long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
499: long returnCode;
500: long reasonCode;
501: long exitDataLength = 0;
502: long ruleArrayLength = 0;
503: unsigned char exitData[8];
504: unsigned char ruleArray[8];
505: unsigned char keyLabel[64];
506: unsigned long keyLabelLength = strlen(key_id);
507: unsigned char modulus[512];
508: long modulusFieldLength = sizeof(modulus);
509: long modulusLength = 0;
510: unsigned char exponent[512];
511: long exponentLength = sizeof(exponent);
512:
513: if (keyLabelLength > sizeof(keyLabel))
514: {
515: CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
516: CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
517: return NULL;
518: }
519:
520: memset(keyLabel,' ', sizeof(keyLabel));
521: memcpy(keyLabel, key_id, keyLabelLength);
522:
523: keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
524: if (!keyToken)
525: {
526: CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
527: ERR_R_MALLOC_FAILURE);
528: goto err;
529: }
530:
531: keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData,
532: &ruleArrayLength, ruleArray, keyLabel, &keyTokenLength,
533: keyToken+sizeof(long));
534:
535: if (returnCode)
536: {
537: CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
538: ERR_R_