1 /*
2  * COPYRIGHT (c) International Business Machines Corp. 2001-2017
3  *
4  * This program is provided under the terms of the Common Public License,
5  * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
6  * software constitutes recipient's acceptance of CPL-1.0 terms which can be
7  * found in the file LICENSE file or at
8  * https://opensource.org/licenses/cpl1.0.php
9  */
10 
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdint.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <openssl/des.h>
18 #include <openssl/aes.h>
19 #include <fcntl.h>
20 #include "pkcs11types.h"
21 #include "p11util.h"
22 #include "defs.h"
23 #include "host_defs.h"
24 #include "h_extern.h"
25 #include "trace.h"
26 #include "sw_crypt.h"
27 
sw_des3_cbc(CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,CK_BYTE * init_v,CK_BYTE * key_value,CK_BYTE encrypt)28 CK_RV sw_des3_cbc(CK_BYTE *in_data,
29                   CK_ULONG in_data_len,
30                   CK_BYTE *out_data,
31                   CK_ULONG *out_data_len,
32                   CK_BYTE *init_v, CK_BYTE *key_value, CK_BYTE encrypt)
33 {
34     DES_key_schedule des_key1;
35     DES_key_schedule des_key2;
36     DES_key_schedule des_key3;
37 
38     const_DES_cblock key_SSL1, key_SSL2, key_SSL3;
39     DES_cblock ivec;
40 
41     // the des decrypt will only fail if the data length is not evenly divisible
42     // by DES_BLOCK_SIZE
43     if (in_data_len % DES_BLOCK_SIZE) {
44         TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
45         return CKR_DATA_LEN_RANGE;
46     }
47     // The key as passed in is a 24 byte string containing 3 keys
48     // pick it apart and create the key schedules
49     memcpy(&key_SSL1, key_value, (size_t) 8);
50     memcpy(&key_SSL2, key_value + 8, (size_t) 8);
51     memcpy(&key_SSL3, key_value + 16, (size_t) 8);
52     DES_set_key_unchecked(&key_SSL1, &des_key1);
53     DES_set_key_unchecked(&key_SSL2, &des_key2);
54     DES_set_key_unchecked(&key_SSL3, &des_key3);
55 
56     memcpy(ivec, init_v, sizeof(ivec));
57 
58     // Encrypt or decrypt the data
59     if (encrypt) {
60         DES_ede3_cbc_encrypt(in_data,
61                              out_data,
62                              in_data_len,
63                              &des_key1,
64                              &des_key2, &des_key3, &ivec, DES_ENCRYPT);
65         *out_data_len = in_data_len;
66     } else {
67         DES_ede3_cbc_encrypt(in_data,
68                              out_data,
69                              in_data_len,
70                              &des_key1,
71                              &des_key2, &des_key3, &ivec, DES_DECRYPT);
72 
73         *out_data_len = in_data_len;
74     }
75 
76     return CKR_OK;
77 }
78 
sw_aes_cbc(CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,CK_BYTE * init_v,CK_BYTE * key_value,CK_ULONG keylen,CK_BYTE encrypt)79 CK_RV sw_aes_cbc(CK_BYTE *in_data,
80                  CK_ULONG in_data_len,
81                  CK_BYTE *out_data,
82                  CK_ULONG *out_data_len,
83                  CK_BYTE *init_v, CK_BYTE *key_value, CK_ULONG keylen,
84                  CK_BYTE encrypt)
85 {
86     AES_KEY aes_key;
87 
88     UNUSED(out_data_len); //XXX can this parameter be removed ?
89 
90     memset(&aes_key, 0, sizeof(aes_key));
91 
92     // the aes decrypt will only fail if the data length is not evenly divisible
93     // by AES_BLOCK_SIZE
94     if (in_data_len % AES_BLOCK_SIZE) {
95         TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
96         return CKR_DATA_LEN_RANGE;
97     }
98 
99     // Encrypt or decrypt the data
100     if (encrypt) {
101         AES_set_encrypt_key(key_value, keylen * 8, &aes_key);
102         AES_cbc_encrypt(in_data, out_data, in_data_len, &aes_key,
103                         init_v, AES_ENCRYPT);
104     } else {
105         AES_set_decrypt_key(key_value, keylen * 8, &aes_key);
106         AES_cbc_encrypt(in_data,  out_data, in_data_len, &aes_key,
107                         init_v, AES_DECRYPT);
108     }
109 
110     return CKR_OK;
111 }
112