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 // File:  mech_des.c
12 //
13 // Mechanisms for DES
14 //
15 
16 #include <string.h>             // for memcmp() et al
17 #include <stdlib.h>
18 
19 #include "pkcs11types.h"
20 #include "defs.h"
21 #include "host_defs.h"
22 #include "h_extern.h"
23 #include "tok_spec_struct.h"
24 #include "trace.h"
25 
26 #include <openssl/crypto.h>
27 
28 //
29 //
pk_des_ecb_encrypt(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)30 CK_RV pk_des_ecb_encrypt(STDLL_TokData_t *tokdata,
31                          SESSION *sess,
32                          CK_BBOOL length_only,
33                          ENCR_DECR_CONTEXT *ctx,
34                          CK_BYTE *in_data,
35                          CK_ULONG in_data_len,
36                          CK_BYTE *out_data, CK_ULONG *out_data_len)
37 {
38     OBJECT *key = NULL;
39     CK_RV rc;
40 
41 
42     if (!sess || !ctx || !out_data_len) {
43         TRACE_ERROR("%s received bad argument(s)\n", __func__);
44         return CKR_FUNCTION_FAILED;
45     }
46     // CKM_DES_ECB requires the input data to be an integral
47     // multiple of the block size
48     //
49     if (in_data_len % DES_BLOCK_SIZE != 0) {
50         TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
51         return CKR_DATA_LEN_RANGE;
52     }
53     rc = object_mgr_find_in_map1(tokdata, ctx->key, &key);
54     if (rc != CKR_OK) {
55         TRACE_ERROR("Failed to find specified object.\n");
56         return rc;
57     }
58 
59     if (length_only == TRUE) {
60         *out_data_len = in_data_len;
61         return CKR_OK;
62     }
63 
64     if (*out_data_len < in_data_len) {
65         *out_data_len = in_data_len;
66         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
67         return CKR_BUFFER_TOO_SMALL;
68     }
69 
70     return ckm_des_ecb_encrypt(tokdata, in_data, in_data_len,
71                                out_data, out_data_len, key);
72 }
73 
74 
75 //
76 //
des_ecb_decrypt(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)77 CK_RV des_ecb_decrypt(STDLL_TokData_t *tokdata,
78                       SESSION *sess,
79                       CK_BBOOL length_only,
80                       ENCR_DECR_CONTEXT *ctx,
81                       CK_BYTE *in_data,
82                       CK_ULONG in_data_len,
83                       CK_BYTE *out_data, CK_ULONG *out_data_len)
84 {
85     OBJECT *key = NULL;
86     CK_RV rc;
87 
88 
89     if (!sess || !ctx || !out_data_len) {
90         TRACE_ERROR("%s received bad argument(s)\n", __func__);
91         return CKR_FUNCTION_FAILED;
92     }
93     // CKM_DES_ECB requires the input data to be an integral
94     // multiple of the block size
95     //
96     if (in_data_len % DES_BLOCK_SIZE != 0) {
97         TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE));
98         return CKR_ENCRYPTED_DATA_LEN_RANGE;
99     }
100     rc = object_mgr_find_in_map1(tokdata, ctx->key, &key);
101     if (rc != CKR_OK) {
102         TRACE_ERROR("Failed to find specified object.\n");
103         return rc;
104     }
105 
106     if (length_only == TRUE) {
107         *out_data_len = in_data_len;
108         return CKR_OK;
109     }
110 
111     if (*out_data_len < in_data_len) {
112         *out_data_len = in_data_len;
113         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
114         return CKR_BUFFER_TOO_SMALL;
115     }
116 
117     return ckm_des_ecb_decrypt(tokdata, in_data, in_data_len,
118                                out_data, out_data_len, key);
119 }
120 
121 
122 //
123 //
pk_des_cbc_encrypt(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)124 CK_RV pk_des_cbc_encrypt(STDLL_TokData_t *tokdata,
125                          SESSION *sess,
126                          CK_BBOOL length_only,
127                          ENCR_DECR_CONTEXT *ctx,
128                          CK_BYTE *in_data,
129                          CK_ULONG in_data_len,
130                          CK_BYTE *out_data, CK_ULONG *out_data_len)
131 {
132     OBJECT *key = NULL;
133     CK_RV rc;
134 
135     if (!sess || !ctx || !out_data_len) {
136         TRACE_ERROR("%s received bad argument(s)\n", __func__);
137         return CKR_FUNCTION_FAILED;
138     }
139     // CKM_DES_CBC requires the input data to be an integral
140     // multiple of the block size
141     //
142     if (in_data_len % DES_BLOCK_SIZE != 0) {
143         TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
144         return CKR_DATA_LEN_RANGE;
145     }
146     rc = object_mgr_find_in_map1(tokdata, ctx->key, &key);
147     if (rc != CKR_OK) {
148         TRACE_ERROR("Failed to find specified object.\n");
149         return rc;
150     }
151 
152     if (length_only == TRUE) {
153         *out_data_len = in_data_len;
154         return CKR_OK;
155     }
156 
157     if (*out_data_len < in_data_len) {
158         *out_data_len = in_data_len;
159         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
160         return CKR_BUFFER_TOO_SMALL;
161     }
162 
163     return ckm_des_cbc_encrypt(tokdata, in_data, in_data_len, out_data,
164                                out_data_len, ctx->mech.pParameter, key);
165 }
166 
167 
168 //
169 //
des_cbc_decrypt(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)170 CK_RV des_cbc_decrypt(STDLL_TokData_t *tokdata,
171                       SESSION *sess,
172                       CK_BBOOL length_only,
173                       ENCR_DECR_CONTEXT *ctx,
174                       CK_BYTE *in_data,
175                       CK_ULONG in_data_len,
176                       CK_BYTE *out_data, CK_ULONG *out_data_len)
177 {
178     OBJECT *key = NULL;
179     CK_RV rc;
180 
181 
182     if (!sess || !ctx || !out_data_len) {
183         TRACE_ERROR("%s received bad argument(s)\n", __func__);
184         return CKR_FUNCTION_FAILED;
185     }
186     // CKM_DES_CBC requires the input data to be an integral
187     // multiple of the block size
188     //
189     if (in_data_len % DES_BLOCK_SIZE != 0) {
190         TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE));
191         return CKR_ENCRYPTED_DATA_LEN_RANGE;
192     }
193     rc = object_mgr_find_in_map1(tokdata, ctx->key, &key);
194     if (rc != CKR_OK) {
195         TRACE_ERROR("Failed to find specified object.\n");
196         return rc;
197     }
198 
199     if (length_only == TRUE) {
200         *out_data_len = in_data_len;
201         return CKR_OK;
202     }
203 
204     if (*out_data_len < in_data_len) {
205         *out_data_len = in_data_len;
206         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
207         return CKR_BUFFER_TOO_SMALL;
208     }
209 
210     return ckm_des_cbc_decrypt(tokdata, in_data, in_data_len, out_data,
211                                out_data_len, ctx->mech.pParameter, key);
212 }
213 
214 
215 //
216 //
des_cbc_pad_encrypt(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)217 CK_RV des_cbc_pad_encrypt(STDLL_TokData_t *tokdata,
218                           SESSION *sess,
219                           CK_BBOOL length_only,
220                           ENCR_DECR_CONTEXT *ctx,
221                           CK_BYTE *in_data,
222                           CK_ULONG in_data_len,
223                           CK_BYTE *out_data, CK_ULONG *out_data_len)
224 {
225     OBJECT *key = NULL;
226     CK_BYTE *clear = NULL;
227     CK_ULONG padded_len;
228     CK_RV rc;
229 
230     if (!sess || !ctx || !out_data_len) {
231         TRACE_ERROR("%s received bad argument(s)\n", __func__);
232         return CKR_FUNCTION_FAILED;
233     }
234     // DES-CBC-PAD has no input length requirements
235     //
236 
237     rc = object_mgr_find_in_map1(tokdata, ctx->key, &key);
238     if (rc != CKR_OK) {
239         TRACE_ERROR("Failed to find specified object.\n");
240         return rc;
241     }
242     // compute the output length, accounting for padding
243     //
244     padded_len = DES_BLOCK_SIZE * (in_data_len / DES_BLOCK_SIZE + 1);
245 
246     if (length_only == TRUE) {
247         *out_data_len = padded_len;
248         return CKR_OK;
249     }
250 
251     if (*out_data_len < padded_len) {
252         *out_data_len = padded_len;
253         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
254         return CKR_BUFFER_TOO_SMALL;
255     }
256 
257     clear = (CK_BYTE *) malloc(padded_len);
258     if (!clear) {
259         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
260         return CKR_HOST_MEMORY;
261     }
262     memcpy(clear, in_data, in_data_len);
263 
264     add_pkcs_padding(clear + in_data_len,
265                      DES_BLOCK_SIZE, in_data_len, padded_len);
266 
267     rc = ckm_des_cbc_encrypt(tokdata, clear, padded_len, out_data, out_data_len,
268                              ctx->mech.pParameter, key);
269     free(clear);
270 
271     return rc;
272 }
273 
274 
275 //
276 //
des_cbc_pad_decrypt(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)277 CK_RV des_cbc_pad_decrypt(STDLL_TokData_t *tokdata,
278                           SESSION *sess,
279                           CK_BBOOL length_only,
280                           ENCR_DECR_CONTEXT *ctx,
281                           CK_BYTE *in_data,
282                           CK_ULONG in_data_len,
283                           CK_BYTE *out_data, CK_ULONG *out_data_len)
284 {
285     OBJECT *key = NULL;
286     CK_BYTE *clear = NULL;
287     CK_ULONG padded_len;
288     CK_RV rc;
289 
290 
291     if (!sess || !ctx || !out_data_len) {
292         TRACE_ERROR("%s received bad argument(s)\n", __func__);
293         return CKR_FUNCTION_FAILED;
294     }
295     //
296     // no need to validate the input length since we'll pad as necessary
297     //
298 
299     rc = object_mgr_find_in_map1(tokdata, ctx->key, &key);
300     if (rc != CKR_OK) {
301         TRACE_ERROR("Failed to find specified object.\n");
302         return rc;
303     }
304     // we're decrypting so even with CBC-PAD, we should have an integral
305     // number of block to decrypt
306     //
307     if (in_data_len % DES_BLOCK_SIZE != 0) {
308         TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE));
309         return CKR_ENCRYPTED_DATA_LEN_RANGE;
310     }
311     // the amount of cleartext after stripping the padding will actually be less
312     // than the input bytes...
313     //
314     padded_len = in_data_len;
315 
316     if (length_only == TRUE) {
317         *out_data_len = padded_len;
318         return CKR_OK;
319     }
320 
321     clear = (CK_BYTE *) malloc(padded_len);
322     if (!clear) {
323         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
324         return CKR_HOST_MEMORY;
325     }
326     rc = ckm_des_cbc_decrypt(tokdata, in_data, in_data_len, clear, &padded_len,
327                              ctx->mech.pParameter, key);
328 
329     if (rc == CKR_OK) {
330         strip_pkcs_padding(clear, padded_len, out_data_len);
331         memcpy(out_data, clear, *out_data_len);
332     }
333 
334     free(clear);
335 
336     return rc;
337 }
338 
339 
340 //
341 //
des_ecb_encrypt_update(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)342 CK_RV des_ecb_encrypt_update(STDLL_TokData_t *tokdata,
343                              SESSION *sess,
344                              CK_BBOOL length_only,
345                              ENCR_DECR_CONTEXT *ctx,
346                              CK_BYTE *in_data,
347                              CK_ULONG in_data_len,
348                              CK_BYTE *out_data, CK_ULONG *out_data_len)
349 {
350     DES_CONTEXT *context = NULL;
351     OBJECT *key = NULL;
352     CK_BYTE *clear = NULL;
353     CK_ULONG total, remain, out_len;
354     CK_RV rc;
355 
356     if (!sess || !ctx || !out_data_len) {
357         TRACE_ERROR("%s received bad argument(s)\n", __func__);
358         return CKR_FUNCTION_FAILED;
359     }
360     context = (DES_CONTEXT *) ctx->context;
361 
362     total = (context->len + in_data_len);
363 
364     if (total < DES_BLOCK_SIZE) {
365         if (length_only == FALSE && in_data_len) {
366             memcpy(context->data + context->len, in_data, in_data_len);
367             context->len += in_data_len;
368         }
369         *out_data_len = 0;
370         return CKR_OK;
371     } else {
372         // we have at least 1 block
373         //
374         remain = (total % DES_BLOCK_SIZE);
375         out_len = (total - remain);     // should always be at least 1 block
376 
377         if (length_only == TRUE) {
378             *out_data_len = out_len;
379             return CKR_OK;
380         }
381 
382         rc = object_mgr_find_in_map_nocache(ctx->key, &key);
383         if (rc != CKR_OK) {
384             TRACE_ERROR("Failed to find specified object.\n");
385             return rc;
386         }
387 
388         clear = (CK_BYTE *) malloc(out_len);
389         if (!clear) {
390             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
391             return CKR_HOST_MEMORY;
392         }
393         // copy any data left over from the previous encryption operation first
394         //
395         memcpy(clear, context->data, context->len);
396         memcpy(clear + context->len, in_data, out_len - context->len);
397 
398         rc = ckm_des_ecb_encrypt(tokdata, clear, out_len, out_data,
399                                  out_data_len, key);
400         if (rc == CKR_OK) {
401             *out_data_len = out_len;
402 
403             // update the context buffer.  we already used the buffer's current
404             // contents so we completely overwrite it
405             //
406             if (remain != 0)
407                 memcpy(context->data, in_data + (in_data_len - remain), remain);
408             context->len = remain;
409         }
410         free(clear);
411         return rc;
412     }
413 }
414 
415 
416 //
417 //
des_ecb_decrypt_update(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)418 CK_RV des_ecb_decrypt_update(STDLL_TokData_t *tokdata,
419                              SESSION *sess,
420                              CK_BBOOL length_only,
421                              ENCR_DECR_CONTEXT *ctx,
422                              CK_BYTE *in_data,
423                              CK_ULONG in_data_len,
424                              CK_BYTE *out_data, CK_ULONG *out_data_len)
425 {
426     DES_CONTEXT *context = NULL;
427     OBJECT *key = NULL;
428     CK_BYTE *cipher = NULL;
429     CK_ULONG total, remain, out_len;
430     CK_RV rc;
431 
432     if (!sess || !ctx || !out_data_len) {
433         TRACE_ERROR("%s received bad argument(s)\n", __func__);
434         return CKR_FUNCTION_FAILED;
435     }
436     context = (DES_CONTEXT *) ctx->context;
437 
438     total = (context->len + in_data_len);
439 
440     if (total < DES_BLOCK_SIZE) {
441         if (length_only == FALSE && in_data_len) {
442             memcpy(context->data + context->len, in_data, in_data_len);
443             context->len += in_data_len;
444         }
445 
446         *out_data_len = 0;
447         return CKR_OK;
448     } else {
449         // we have at least 1 block
450         //
451         remain = (total % DES_BLOCK_SIZE);
452         out_len = total - remain;
453 
454         if (length_only == TRUE) {
455             *out_data_len = out_len;
456             return CKR_OK;
457         }
458 
459         rc = object_mgr_find_in_map_nocache(ctx->key, &key);
460         if (rc != CKR_OK) {
461             TRACE_ERROR("Failed to find specified object.\n");
462             return rc;
463         }
464 
465         cipher = (CK_BYTE *) malloc(out_len);
466         if (!cipher) {
467             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
468             return CKR_HOST_MEMORY;
469         }
470         // copy any data left over from the previous decryption operation first
471         //
472         memcpy(cipher, context->data, context->len);
473         memcpy(cipher + context->len, in_data, out_len - context->len);
474 
475         rc = ckm_des_ecb_decrypt(tokdata, cipher, out_len, out_data,
476                                  out_data_len, key);
477         if (rc == CKR_OK) {
478             *out_data_len = out_len;
479 
480             // copy the remaining 'new' input data to the context buffer
481             //
482             if (remain != 0)
483                 memcpy(context->data, in_data + (in_data_len - remain), remain);
484             context->len = remain;
485         }
486         free(cipher);
487         return rc;
488     }
489 }
490 
491 
492 //
493 //
des_cbc_encrypt_update(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)494 CK_RV des_cbc_encrypt_update(STDLL_TokData_t *tokdata,
495                              SESSION *sess,
496                              CK_BBOOL length_only,
497                              ENCR_DECR_CONTEXT *ctx,
498                              CK_BYTE *in_data,
499                              CK_ULONG in_data_len,
500                              CK_BYTE *out_data, CK_ULONG *out_data_len)
501 {
502     DES_CONTEXT *context = NULL;
503     OBJECT *key = NULL;
504     CK_BYTE *clear = NULL;
505     CK_ULONG total, remain, out_len;
506     CK_RV rc;
507 
508 
509     if (!sess || !ctx || !out_data_len) {
510         TRACE_ERROR("%s received bad argument(s)\n", __func__);
511         return CKR_FUNCTION_FAILED;
512     }
513     context = (DES_CONTEXT *) ctx->context;
514 
515     total = (context->len + in_data_len);
516 
517     if (total < DES_BLOCK_SIZE) {
518         if (length_only == FALSE && in_data_len) {
519             memcpy(context->data + context->len, in_data, in_data_len);
520             context->len += in_data_len;
521         }
522 
523         *out_data_len = 0;
524         return CKR_OK;
525     } else {
526         // we have at least 1 block
527         //
528         remain = (total % DES_BLOCK_SIZE);
529         out_len = total - remain;
530 
531         if (length_only == TRUE) {
532             *out_data_len = out_len;
533             return CKR_OK;
534         }
535 
536         rc = object_mgr_find_in_map_nocache(ctx->key, &key);
537         if (rc != CKR_OK) {
538             TRACE_ERROR("Failed to find specified object.\n");
539             return rc;
540         }
541         // these buffers need to be longword aligned
542         //
543         clear = (CK_BYTE *) malloc(out_len);
544         if (!clear) {
545             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
546             return CKR_HOST_MEMORY;
547         }
548         // copy any data left over from the previous encryption operation first
549         //
550         memcpy(clear, context->data, context->len);
551         memcpy(clear + context->len, in_data, out_len - context->len);
552 
553         rc = ckm_des_cbc_encrypt(tokdata, clear, out_len, out_data,
554                                  out_data_len, ctx->mech.pParameter, key);
555         if (rc == CKR_OK) {
556             *out_data_len = out_len;
557 
558             // the new init_v is the last encrypted data block
559             //
560             memcpy(ctx->mech.pParameter,
561                    out_data + (*out_data_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE);
562 
563             // copy the remaining 'new' input data to the context buffer
564             //
565             if (remain != 0)
566                 memcpy(context->data, in_data + (in_data_len - remain), remain);
567             context->len = remain;
568         }
569 
570         free(clear);
571         return rc;
572     }
573 }
574 
575 
576 //
577 //
des_cbc_decrypt_update(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)578 CK_RV des_cbc_decrypt_update(STDLL_TokData_t *tokdata,
579                              SESSION *sess,
580                              CK_BBOOL length_only,
581                              ENCR_DECR_CONTEXT *ctx,
582                              CK_BYTE *in_data,
583                              CK_ULONG in_data_len,
584                              CK_BYTE *out_data, CK_ULONG *out_data_len)
585 {
586     DES_CONTEXT *context = NULL;
587     OBJECT *key = NULL;
588     CK_BYTE *cipher = NULL;
589     CK_ULONG total, remain, out_len;
590     CK_RV rc;
591 
592 
593     if (!sess || !ctx || !out_data_len) {
594         TRACE_ERROR("%s received bad argument(s)\n", __func__);
595         return CKR_FUNCTION_FAILED;
596     }
597     context = (DES_CONTEXT *) ctx->context;
598 
599     total = context->len + in_data_len;
600 
601     if (total < DES_BLOCK_SIZE) {
602         if (length_only == FALSE && in_data_len) {
603             memcpy(context->data + context->len, in_data, in_data_len);
604             context->len += in_data_len;
605         }
606 
607         *out_data_len = 0;
608         return CKR_OK;
609     } else {
610         // we have at least 1 block
611         //
612         remain = total % DES_BLOCK_SIZE;
613         out_len = total - remain;
614 
615         if (length_only == TRUE) {
616             *out_data_len = out_len;
617             return CKR_OK;
618         }
619 
620         rc = object_mgr_find_in_map_nocache(ctx->key, &key);
621         if (rc != CKR_OK) {
622             TRACE_ERROR("Failed to find specified object.\n");
623             return rc;
624         }
625         // these buffers need to be longword aligned
626         //
627         cipher = (CK_BYTE *) malloc(out_len);
628         if (!cipher) {
629             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
630             return CKR_HOST_MEMORY;
631         }
632         // copy any data left over from the previous decryption operation first
633         //
634         memcpy(cipher, context->data, context->len);
635         memcpy(cipher + context->len, in_data, out_len - context->len);
636 
637         rc = ckm_des_cbc_decrypt(tokdata, cipher, out_len, out_data,
638                                  out_data_len, ctx->mech.pParameter, key);
639         if (rc == CKR_OK) {
640             *out_data_len = out_len;
641 
642             // the new init_v is the last decrypted data block
643             //
644             memcpy(ctx->mech.pParameter, cipher + (out_len - DES_BLOCK_SIZE),
645                    DES_BLOCK_SIZE);
646 
647             // copy the remaining 'new' input data to the context buffer
648             //
649             if (remain != 0)
650                 memcpy(context->data, in_data + (in_data_len - remain), remain);
651             context->len = remain;
652         }
653 
654         free(cipher);
655         return rc;
656     }
657 }
658 
659 
660 //
661 //
des_cbc_pad_encrypt_update(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)662 CK_RV des_cbc_pad_encrypt_update(STDLL_TokData_t *tokdata,
663                                  SESSION *sess,
664                                  CK_BBOOL length_only,
665                                  ENCR_DECR_CONTEXT *ctx,
666                                  CK_BYTE *in_data,
667                                  CK_ULONG in_data_len,
668                                  CK_BYTE *out_data, CK_ULONG *out_data_len)
669 {
670     DES_CONTEXT *context = NULL;
671     OBJECT *key = NULL;
672     CK_BYTE *clear = NULL;
673     CK_ULONG total, remain, out_len;
674     CK_RV rc;
675 
676 
677     if (!sess || !ctx || !out_data_len) {
678         TRACE_ERROR("%s received bad argument(s)\n", __func__);
679         return CKR_FUNCTION_FAILED;
680     }
681     context = (DES_CONTEXT *) ctx->context;
682 
683     total = (context->len + in_data_len);
684 
685     // note, this is subtly different from the other encrypt update routines
686     //
687     if (total <= DES_BLOCK_SIZE) {
688         if (length_only == FALSE) {
689             memcpy(context->data + context->len, in_data, in_data_len);
690             context->len += in_data_len;
691         }
692 
693         *out_data_len = 0;
694         return CKR_OK;
695     } else {
696         // we have at least 1 block + 1 byte
697         //
698         remain = total % DES_BLOCK_SIZE;
699         out_len = total - remain;
700 
701         if (remain == 0) {
702             remain = DES_BLOCK_SIZE;
703             out_len -= DES_BLOCK_SIZE;
704         }
705 
706         if (length_only == TRUE) {
707             *out_data_len = out_len;
708             return CKR_OK;
709         }
710         // at this point, we should have:
711         //    1) remain != 0
712         //    2) out_len != 0
713         //
714         rc = object_mgr_find_in_map_nocache(ctx->key, &key);
715         if (rc != CKR_OK) {
716             TRACE_ERROR("Failed to find specified object.\n");
717             return rc;
718         }
719         // these buffers need to be longword aligned
720         //
721         clear = (CK_BYTE *) malloc(out_len);
722         if (!clear) {
723             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
724             return CKR_HOST_MEMORY;
725         }
726         // copy any data left over from the previous encryption operation first
727         //
728         memcpy(clear, context->data, context->len);
729         memcpy(clear + context->len, in_data, out_len - context->len);
730 
731         //
732         // we don't do padding during the update
733         //
734         rc = ckm_des_cbc_encrypt(tokdata, clear, out_len, out_data,
735                                  out_data_len, ctx->mech.pParameter, key);
736 
737         if (rc == CKR_OK) {
738             // the new init_v is the last encrypted data block
739             //
740             memcpy(ctx->mech.pParameter,
741                    out_data + (*out_data_len - DES_BLOCK_SIZE), DES_BLOCK_SIZE);
742 
743             // copy the remaining 'new' input data to the temporary space
744             //
745             memcpy(context->data, in_data + (in_data_len - remain), remain);
746             context->len = remain;
747         }
748 
749         free(clear);
750         return rc;
751     }
752 }
753 
754 
755 //
756 //
des_cbc_pad_decrypt_update(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)757 CK_RV des_cbc_pad_decrypt_update(STDLL_TokData_t *tokdata,
758                                  SESSION *sess,
759                                  CK_BBOOL length_only,
760                                  ENCR_DECR_CONTEXT *ctx,
761                                  CK_BYTE *in_data,
762                                  CK_ULONG in_data_len,
763                                  CK_BYTE *out_data, CK_ULONG *out_data_len)
764 {
765     DES_CONTEXT *context = NULL;
766     OBJECT *key = NULL;
767     CK_BYTE *cipher = NULL;
768     CK_ULONG total, remain, out_len;
769     CK_RV rc;
770 
771 
772     if (!sess || !ctx || !out_data_len) {
773         TRACE_ERROR("%s received bad argument(s)\n", __func__);
774         return CKR_FUNCTION_FAILED;
775     }
776     context = (DES_CONTEXT *) ctx->context;
777 
778     total = (context->len + in_data_len);
779 
780     // note, this is subtly different from the other decrypt update routines
781     //
782     if (total <= DES_BLOCK_SIZE) {
783         if (length_only == FALSE) {
784             memcpy(context->data + context->len, in_data, in_data_len);
785             context->len += in_data_len;
786         }
787 
788         *out_data_len = 0;
789         return CKR_OK;
790     } else {
791         // we have at least 1 block + 1 byte
792         //
793         remain = total % DES_BLOCK_SIZE;
794         out_len = total - remain;
795 
796         if (remain == 0) {
797             remain = DES_BLOCK_SIZE;
798             out_len -= DES_BLOCK_SIZE;
799         }
800 
801         if (length_only == TRUE) {
802             *out_data_len = out_len;
803             return CKR_OK;
804         }
805         // at this point, we should have:
806         //    1) remain != 0
807         //    2) out_len != 0
808         //
809         rc = object_mgr_find_in_map_nocache(ctx->key, &key);
810         if (rc != CKR_OK) {
811             TRACE_ERROR("Failed to find specified object.\n");
812             return rc;
813         }
814         // these buffers need to be longword aligned
815         //
816         cipher = (CK_BYTE *) malloc(out_len);
817         if (!cipher) {
818             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
819             return CKR_HOST_MEMORY;
820         }
821         // copy any data left over from the previous decryption operation first
822         //
823         memcpy(cipher, context->data, context->len);
824         memcpy(cipher + context->len, in_data, out_len - context->len);
825 
826         rc = ckm_des_cbc_decrypt(tokdata, cipher, out_len, out_data,
827                                  out_data_len, ctx->mech.pParameter, key);
828 
829         if (rc == CKR_OK) {
830             // the new init_v is the last decrypted data block
831             //
832             memcpy(ctx->mech.pParameter, cipher + (out_len - DES_BLOCK_SIZE),
833                    DES_BLOCK_SIZE);
834 
835             // copy the remaining 'new' input data to the temporary space
836             //
837             memcpy(context->data, in_data + (in_data_len - remain), remain);
838             context->len = remain;
839         }
840         free(cipher);
841         return rc;
842     }
843 }
844 
845 
846 //
847 //
des_ecb_encrypt_final(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * out_data,CK_ULONG * out_data_len)848 CK_RV des_ecb_encrypt_final(STDLL_TokData_t *tokdata,
849                             SESSION *sess,
850                             CK_BBOOL length_only,
851                             ENCR_DECR_CONTEXT *ctx,
852                             CK_BYTE *out_data, CK_ULONG *out_data_len)
853 {
854     DES_CONTEXT *context = NULL;
855 
856     UNUSED(tokdata);
857     UNUSED(out_data);
858 
859     if (!sess || !ctx || !out_data_len) {
860         TRACE_ERROR("%s received bad argument(s)\n", __func__);
861         return CKR_FUNCTION_FAILED;
862     }
863     // satisfy the compiler
864     //
865     if (length_only)
866         context = NULL;
867 
868     context = (DES_CONTEXT *) ctx->context;
869 
870     // DES-ECB does no padding so there had better not be
871     // any data in the context buffer.  if there is it means
872     // that the overall data length was not a multiple of the blocksize
873     //
874     if (context->len != 0) {
875         TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
876         return CKR_DATA_LEN_RANGE;
877     }
878 
879     *out_data_len = 0;
880 
881     return CKR_OK;
882 }
883 
884 
885 //
886 //
des_ecb_decrypt_final(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * out_data,CK_ULONG * out_data_len)887 CK_RV des_ecb_decrypt_final(STDLL_TokData_t *tokdata,
888                             SESSION *sess,
889                             CK_BBOOL length_only,
890                             ENCR_DECR_CONTEXT *ctx,
891                             CK_BYTE *out_data, CK_ULONG *out_data_len)
892 {
893     DES_CONTEXT *context = NULL;
894 
895     UNUSED(tokdata);
896     UNUSED(out_data);
897 
898     if (!sess || !ctx || !out_data_len) {
899         TRACE_ERROR("%s received bad argument(s)\n", __func__);
900         return CKR_FUNCTION_FAILED;
901     }
902     // satisfy the compiler
903     //
904     if (length_only)
905         context = NULL;
906 
907     context = (DES_CONTEXT *) ctx->context;
908 
909     // DES-ECB does no padding so there had better not be
910     // any data in the context buffer.  if there is it means
911     // that the overall data length was not a multiple of the blocksize
912     //
913     if (context->len != 0) {
914         TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE));
915         return CKR_ENCRYPTED_DATA_LEN_RANGE;
916     }
917 
918     *out_data_len = 0;
919 
920     return CKR_OK;
921 }
922 
923 
924 //
925 //
des_cbc_encrypt_final(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * out_data,CK_ULONG * out_data_len)926 CK_RV des_cbc_encrypt_final(STDLL_TokData_t *tokdata,
927                             SESSION *sess,
928                             CK_BBOOL length_only,
929                             ENCR_DECR_CONTEXT *ctx,
930                             CK_BYTE *out_data, CK_ULONG *out_data_len)
931 {
932     DES_CONTEXT *context = NULL;
933 
934     UNUSED(tokdata);
935     UNUSED(out_data);
936 
937     if (!sess || !ctx || !out_data_len) {
938         TRACE_ERROR("%s received bad argument(s)\n", __func__);
939         return CKR_FUNCTION_FAILED;
940     }
941     // satisfy the compiler
942     //
943     if (length_only)
944         context = NULL;
945 
946     context = (DES_CONTEXT *) ctx->context;
947 
948     // DES-CBC does no padding so there had better not be
949     // any data in the context buffer.  if there is it means
950     // that the overall data length was not a multiple of the blocksize
951     //
952     if (context->len != 0) {
953         TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
954         return CKR_DATA_LEN_RANGE;
955     }
956 
957     *out_data_len = 0;
958 
959     return CKR_OK;
960 }
961 
962 
963 //
964 //
des_cbc_decrypt_final(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * out_data,CK_ULONG * out_data_len)965 CK_RV des_cbc_decrypt_final(STDLL_TokData_t *tokdata,
966                             SESSION *sess,
967                             CK_BBOOL length_only,
968                             ENCR_DECR_CONTEXT *ctx,
969                             CK_BYTE *out_data, CK_ULONG *out_data_len)
970 {
971     DES_CONTEXT *context = NULL;
972 
973     UNUSED(tokdata);
974     UNUSED(out_data);
975 
976     if (!sess || !ctx || !out_data_len) {
977         TRACE_ERROR("%s received bad argument(s)\n", __func__);
978         return CKR_FUNCTION_FAILED;
979     }
980     // satisfy the compiler
981     //
982     if (length_only)
983         context = NULL;
984 
985     context = (DES_CONTEXT *) ctx->context;
986 
987     // DES-CBC does no padding so there had better not be
988     // any data in the context buffer.  if there is it means
989     // that the overall data length was not a multiple of the blocksize
990     //
991     if (context->len != 0) {
992         TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE));
993         return CKR_ENCRYPTED_DATA_LEN_RANGE;
994     }
995 
996     *out_data_len = 0;
997 
998     return CKR_OK;
999 }
1000 
1001 
1002 //
1003 //
des_cbc_pad_encrypt_final(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * out_data,CK_ULONG * out_data_len)1004 CK_RV des_cbc_pad_encrypt_final(STDLL_TokData_t *tokdata,
1005                                 SESSION *sess,
1006                                 CK_BBOOL length_only,
1007                                 ENCR_DECR_CONTEXT *ctx,
1008                                 CK_BYTE *out_data, CK_ULONG *out_data_len)
1009 {
1010     DES_CONTEXT *context = NULL;
1011     OBJECT *key = NULL;
1012     CK_BYTE clear[2 * DES_BLOCK_SIZE];
1013     CK_ULONG out_len;
1014     CK_RV rc;
1015 
1016 
1017     if (!sess || !ctx || !out_data_len) {
1018         TRACE_ERROR("%s received bad argument(s)\n", __func__);
1019         return CKR_FUNCTION_FAILED;
1020     }
1021 
1022     rc = object_mgr_find_in_map1(tokdata, ctx->key, &key);
1023     if (rc != CKR_OK) {
1024         TRACE_ERROR("Failed to find specified object.\n");
1025         return rc;
1026     }
1027 
1028     context = (DES_CONTEXT *) ctx->context;
1029 
1030     // there will never be more than one block in the context buffer
1031     // so the amount of output is as follows:
1032     // if less than 1 block stored, we generate one block of output
1033     // if a full block is stored, we generate two blocks of output (one pad
1034     // block)
1035     //
1036     if (context->len == DES_BLOCK_SIZE)
1037         out_len = 2 * DES_BLOCK_SIZE;
1038     else
1039         out_len = DES_BLOCK_SIZE;
1040 
1041     if (length_only == TRUE) {
1042         *out_data_len = out_len;
1043         return CKR_OK;
1044     } else {
1045         memcpy(clear, context->data, context->len);
1046 
1047         add_pkcs_padding(clear + context->len,
1048                          DES_BLOCK_SIZE, context->len, out_len);
1049 
1050         rc = ckm_des_cbc_encrypt(tokdata, clear, out_len, out_data,
1051                                  out_data_len, ctx->mech.pParameter, key);
1052         return rc;
1053     }
1054 }
1055 
1056 
1057 //
1058 //
des_cbc_pad_decrypt_final(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,ENCR_DECR_CONTEXT * ctx,CK_BYTE * out_data,CK_ULONG * out_data_len)1059 CK_RV des_cbc_pad_decrypt_final(STDLL_TokData_t *tokdata,
1060                                 SESSION *sess,
1061                                 CK_BBOOL length_only,
1062                                 ENCR_DECR_CONTEXT *ctx,
1063                                 CK_BYTE *out_data, CK_ULONG *out_data_len)
1064 {
1065     DES_CONTEXT *context = NULL;
1066     OBJECT *key = NULL;
1067     CK_BYTE clear[DES_BLOCK_SIZE];
1068     CK_BYTE cipher[DES_BLOCK_SIZE];
1069     CK_ULONG out_len;
1070     CK_RV rc;
1071 
1072     if (!sess || !ctx || !out_data_len) {
1073         TRACE_ERROR("%s received bad argument(s)\n", __func__);
1074         return CKR_FUNCTION_FAILED;
1075     }
1076     rc = object_mgr_find_in_map1(tokdata, ctx->key, &key);
1077     if (rc != CKR_OK) {
1078         TRACE_ERROR("Failed to find specified object.\n");
1079         return rc;
1080     }
1081 
1082     context = (DES_CONTEXT *) ctx->context;
1083 
1084     // there had better be a full block in the context buffer
1085     //
1086     if (context->len != DES_BLOCK_SIZE) {
1087         TRACE_ERROR("%s\n", ock_err(ERR_ENCRYPTED_DATA_LEN_RANGE));
1088         return CKR_ENCRYPTED_DATA_LEN_RANGE;
1089     }
1090     // we don't know a priori how much data we'll be returning. we won't
1091     // know until after we decrypt it and strip the padding. it's possible
1092     // that we'll return nothing (the final block might be a padding block).
1093     //
1094     out_len = DES_BLOCK_SIZE;   // upper bound on what we'll return
1095 
1096     if (length_only == TRUE) {
1097         *out_data_len = out_len;
1098         return CKR_OK;
1099     } else {
1100         memcpy(cipher, context->data, DES_BLOCK_SIZE);
1101 
1102         rc = ckm_des_cbc_decrypt(tokdata, cipher, DES_BLOCK_SIZE, clear,
1103                                  &out_len, ctx->mech.pParameter, key);
1104         if (rc == CKR_OK) {
1105             strip_pkcs_padding(clear, DES_BLOCK_SIZE, &out_len);
1106 
1107             if (out_len != 0)
1108                 memcpy(out_data, clear, out_len);
1109 
1110             *out_data_len = out_len;
1111         }
1112 
1113         return rc;
1114     }
1115 }
1116 
1117 
1118 //
1119 // mechanisms
1120 //
1121 
1122 
1123 //
1124 //
ckm_des_key_gen(STDLL_TokData_t * tokdata,TEMPLATE * tmpl)1125 CK_RV ckm_des_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl)
1126 {
1127 
1128     CK_ATTRIBUTE *value_attr = NULL;
1129     CK_ATTRIBUTE *opaque_attr = NULL;
1130     CK_ATTRIBUTE *key_type_attr = NULL;
1131     CK_ATTRIBUTE *class_attr = NULL;
1132     CK_ATTRIBUTE *local_attr = NULL;
1133     CK_BYTE *des_key = NULL;
1134     CK_BYTE dummy_key[DES_KEY_SIZE] = { 0, };
1135     CK_ULONG rc;
1136     CK_ULONG keysize;
1137 
1138     if (token_specific.t_des_key_gen == NULL) {
1139         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
1140         return CKR_MECHANISM_INVALID;
1141     }
1142 
1143     if (is_secure_key_token())
1144         keysize = token_specific.token_keysize;
1145     else
1146         keysize = DES_KEY_SIZE;
1147 
1148     if ((des_key = (CK_BYTE *) calloc(1, keysize)) == NULL) {
1149         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
1150         return CKR_HOST_MEMORY;
1151     }
1152 
1153     rc = token_specific.t_des_key_gen(tokdata, des_key, keysize, DES_KEY_SIZE);
1154     if (rc != CKR_OK)
1155         goto err;
1156 
1157     /* For secure-key keys put in CKA_IBM_OPAQUE
1158      * and put dummy_key in CKA_VALUE.
1159      */
1160     if (is_secure_key_token()) {
1161         opaque_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + keysize);
1162         if (!opaque_attr) {
1163             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
1164             rc = CKR_HOST_MEMORY;
1165             goto err;
1166         }
1167         opaque_attr->type = CKA_IBM_OPAQUE;
1168         opaque_attr->ulValueLen = keysize;
1169         opaque_attr->pValue = (CK_BYTE *) opaque_attr + sizeof(CK_ATTRIBUTE);
1170         memcpy(opaque_attr->pValue, des_key, keysize);
1171         template_update_attribute(tmpl, opaque_attr);
1172     }
1173 
1174     value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + DES_KEY_SIZE);
1175     key_type_attr =
1176         (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
1177     class_attr =
1178         (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS));
1179     local_attr =
1180         (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
1181 
1182     if (!value_attr || !key_type_attr || !class_attr || !local_attr) {
1183         if (value_attr)
1184             free(value_attr);
1185         if (key_type_attr)
1186             free(key_type_attr);
1187         if (class_attr)
1188             free(class_attr);
1189         if (local_attr)
1190             free(local_attr);
1191 
1192         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
1193         rc = CKR_HOST_MEMORY;
1194         goto err;
1195     }
1196 
1197     value_attr->type = CKA_VALUE;
1198     value_attr->ulValueLen = DES_KEY_SIZE;
1199     value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE);
1200     if (is_secure_key_token())
1201         memcpy(value_attr->pValue, dummy_key, DES_KEY_SIZE);
1202     else
1203         memcpy(value_attr->pValue, des_key, DES_KEY_SIZE);
1204     free(des_key);
1205 
1206     key_type_attr->type = CKA_KEY_TYPE;
1207     key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
1208     key_type_attr->pValue = (CK_BYTE *) key_type_attr + sizeof(CK_ATTRIBUTE);
1209     *(CK_KEY_TYPE *) key_type_attr->pValue = CKK_DES;
1210 
1211     class_attr->type = CKA_CLASS;
1212     class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS);
1213     class_attr->pValue = (CK_BYTE *) class_attr + sizeof(CK_ATTRIBUTE);
1214     *(CK_OBJECT_CLASS *) class_attr->pValue = CKO_SECRET_KEY;
1215 
1216     local_attr->type = CKA_LOCAL;
1217     local_attr->ulValueLen = sizeof(CK_BBOOL);
1218     local_attr->pValue = (CK_BYTE *) local_attr + sizeof(CK_ATTRIBUTE);
1219     *(CK_BBOOL *) local_attr->pValue = TRUE;
1220 
1221     template_update_attribute(tmpl, value_attr);
1222     template_update_attribute(tmpl, key_type_attr);
1223     template_update_attribute(tmpl, class_attr);
1224     template_update_attribute(tmpl, local_attr);
1225 
1226     return CKR_OK;
1227 
1228 err:
1229     if (des_key)
1230         free(des_key);
1231 
1232     return rc;
1233 }
1234 
1235 #if !(NOCDMF)
1236 
1237 //
1238 //
ckm_cdmf_key_gen(STDLL_TokData_t * tokdata,TEMPLATE * tmpl)1239 CK_RV ckm_cdmf_key_gen(STDLL_TokData_t *tokdata, TEMPLATE *tmpl)
1240 {
1241     CK_ATTRIBUTE *value_attr = NULL;
1242     CK_ATTRIBUTE *key_type_attr = NULL;
1243     CK_ATTRIBUTE *class_attr = NULL;
1244     CK_ATTRIBUTE *local_attr = NULL;
1245     CK_BYTE cdmf_key[DES_KEY_SIZE];
1246     CK_ULONG repl_len, expected_repl_len;
1247     CK_ULONG rc;
1248 
1249     repl_len = expected_repl_len = DES_KEY_SIZE;
1250 
1251     rc = communicate(PK_CDMF_KEYGEN,
1252                      NULL, 0, cdmf_key, &repl_len, NULL, 0, NULL, 0);
1253 
1254     if (rc == CKR_OK) {
1255         if (repl_len != expected_repl_len)
1256             return CKR_GENERAL_ERROR;
1257     }
1258 
1259     value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + DES_KEY_SIZE);
1260     key_type_attr =
1261         (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
1262     class_attr =
1263         (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS));
1264     local_attr =
1265         (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
1266 
1267     if (!value_attr || !key_type_attr || !class_attr || !local_attr) {
1268         if (value_attr)
1269             free(value_attr);
1270         if (key_type_attr)
1271             free(key_type_attr);
1272         if (class_attr)
1273             free(class_attr);
1274         if (local_attr)
1275             free(local_attr);
1276 
1277         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
1278         return CKR_HOST_MEMORY;
1279     }
1280 
1281     value_attr->type = CKA_VALUE;
1282     value_attr->ulValueLen = DES_KEY_SIZE;
1283     value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE);
1284     memcpy(value_attr->pValue, cdmf_key, DES_KEY_SIZE);
1285 
1286     key_type_attr->type = CKA_KEY_TYPE;
1287     key_type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
1288     key_type_attr->pValue = (CK_BYTE *) key_type_attr + sizeof(CK_ATTRIBUTE);
1289     *(CK_KEY_TYPE *) key_type_attr->pValue = CKK_CDMF;
1290 
1291     class_attr->type = CKA_CLASS;
1292     class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS);
1293     class_attr->pValue = (CK_BYTE *) class_attr + sizeof(CK_ATTRIBUTE);
1294     *(CK_OBJECT_CLASS *) class_attr->pValue = CKO_SECRET_KEY;
1295 
1296     local_attr->type = CKA_LOCAL;
1297     local_attr->ulValueLen = sizeof(CK_BBOOL);
1298     local_attr->pValue = (CK_BYTE *) local_attr + sizeof(CK_ATTRIBUTE);
1299     *(CK_BBOOL *) local_attr->pValue = TRUE;
1300 
1301     template_update_attribute(tmpl, value_attr);
1302     template_update_attribute(tmpl, key_type_attr);
1303     template_update_attribute(tmpl, class_attr);
1304     template_update_attribute(tmpl, local_attr);
1305 
1306     return CKR_OK;
1307 }
1308 
1309 #endif
1310 
1311 //
1312 //
ckm_des_ecb_encrypt(STDLL_TokData_t * tokdata,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,OBJECT * key)1313 CK_RV ckm_des_ecb_encrypt(STDLL_TokData_t *tokdata,
1314                           CK_BYTE *in_data,
1315                           CK_ULONG in_data_len,
1316                           CK_BYTE *out_data,
1317                           CK_ULONG *out_data_len, OBJECT *key)
1318 {
1319     CK_ULONG rc;
1320 
1321 
1322     if (!in_data || !out_data || !key) {
1323         TRACE_ERROR("%s received bad argument(s)\n", __func__);
1324         return CKR_FUNCTION_FAILED;
1325     }
1326     if (*out_data_len < in_data_len) {
1327         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
1328         return CKR_BUFFER_TOO_SMALL;
1329     }
1330 
1331     if (token_specific.t_des_ecb == NULL) {
1332         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
1333         return CKR_MECHANISM_INVALID;
1334     }
1335     rc = token_specific.t_des_ecb(tokdata, in_data, in_data_len,
1336                                   out_data, out_data_len, key, 1);
1337 
1338     if (rc != CKR_OK)
1339         TRACE_DEVEL("Token specific des_ecb encrypt failed.\n");
1340 
1341     return rc;
1342 }
1343 
1344 
1345 //
1346 //
ckm_des_ecb_decrypt(STDLL_TokData_t * tokdata,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,OBJECT * key)1347 CK_RV ckm_des_ecb_decrypt(STDLL_TokData_t *tokdata,
1348                           CK_BYTE *in_data,
1349                           CK_ULONG in_data_len,
1350                           CK_BYTE *out_data,
1351                           CK_ULONG *out_data_len, OBJECT *key)
1352 {
1353     CK_ULONG rc;
1354 
1355 
1356 
1357     if (!in_data || !out_data || !key) {
1358         TRACE_ERROR("%s received bad argument(s)\n", __func__);
1359         return CKR_FUNCTION_FAILED;
1360     }
1361     if (*out_data_len < in_data_len) {
1362         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
1363         return CKR_BUFFER_TOO_SMALL;
1364     }
1365 
1366     if (token_specific.t_des_ecb == NULL) {
1367         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
1368         return CKR_MECHANISM_INVALID;
1369     }
1370     rc = token_specific.t_des_ecb(tokdata, in_data, in_data_len, out_data,
1371                                   out_data_len, key, 0);
1372     if (rc != CKR_OK)
1373         TRACE_ERROR("Token specific des ecb decrypt failed.\n");
1374 
1375     return rc;
1376 }
1377 
1378 
1379 //
1380 //
ckm_des_cbc_encrypt(STDLL_TokData_t * tokdata,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,CK_BYTE * init_v,OBJECT * key)1381 CK_RV ckm_des_cbc_encrypt(STDLL_TokData_t *tokdata,
1382                           CK_BYTE *in_data,
1383                           CK_ULONG in_data_len,
1384                           CK_BYTE *out_data,
1385                           CK_ULONG *out_data_len,
1386                           CK_BYTE *init_v, OBJECT *key)
1387 {
1388     CK_ULONG rc;
1389 
1390 
1391     if (!in_data || !out_data || !init_v || !key) {
1392         TRACE_ERROR("%s received bad argument(s)\n", __func__);
1393         return CKR_FUNCTION_FAILED;
1394     }
1395     if (*out_data_len < in_data_len) {
1396         *out_data_len = in_data_len;
1397         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
1398         return CKR_BUFFER_TOO_SMALL;
1399     }
1400 
1401     if (token_specific.t_des_cbc == NULL) {
1402         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
1403         return CKR_MECHANISM_INVALID;
1404     }
1405     rc = token_specific.t_des_cbc(tokdata, in_data, in_data_len, out_data,
1406                                   out_data_len, key, init_v, 1);
1407 
1408     if (rc != CKR_OK)
1409         TRACE_ERROR("Token specific dec cbc encrypt failed.\n");
1410 
1411     return rc;
1412 }
1413 
1414 
1415 //
1416 //
ckm_des_cbc_decrypt(STDLL_TokData_t * tokdata,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len,CK_BYTE * init_v,OBJECT * key)1417 CK_RV ckm_des_cbc_decrypt(STDLL_TokData_t *tokdata,
1418                           CK_BYTE *in_data,
1419                           CK_ULONG in_data_len,
1420                           CK_BYTE *out_data,
1421                           CK_ULONG *out_data_len,
1422                           CK_BYTE *init_v, OBJECT *key)
1423 {
1424     CK_ULONG rc;
1425 
1426 
1427     if (!in_data || !out_data || !init_v || !key) {
1428         TRACE_ERROR("%s received bad argument(s)\n", __func__);
1429         return CKR_FUNCTION_FAILED;
1430     }
1431     if (*out_data_len < in_data_len) {
1432         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
1433         return CKR_BUFFER_TOO_SMALL;
1434     }
1435 
1436     if (token_specific.t_des_cbc == NULL) {
1437         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
1438         return CKR_MECHANISM_INVALID;
1439     }
1440     rc = token_specific.t_des_cbc(tokdata, in_data, in_data_len, out_data,
1441                                   out_data_len, key, init_v, 0);
1442 
1443     if (rc != CKR_OK)
1444         TRACE_ERROR("Token specific des cbc decrypt failed.\n");
1445 
1446     return rc;
1447 }
1448 
1449 
1450 // we're preparing to wrap a key using DES.  need to make sure the
1451 // data length is a integral multiple of the DES block size.
1452 //
1453 // PKCS #11 specifies that the padding shall be in the form of NULL
1454 // bytes appended to the data
1455 //
1456 // this routine works with either DES and 3DES as the wrapping mechanism
1457 //
ckm_des_wrap_format(STDLL_TokData_t * tokdata,CK_BBOOL length_only,CK_BYTE ** data,CK_ULONG * data_len)1458 CK_RV ckm_des_wrap_format(STDLL_TokData_t *tokdata,
1459                           CK_BBOOL length_only,
1460                           CK_BYTE **data, CK_ULONG *data_len)
1461 {
1462     CK_BYTE *ptr = NULL;
1463     CK_ULONG len1, len2;
1464 
1465     UNUSED(tokdata);
1466 
1467     len1 = *data_len;
1468     if (*data == NULL)
1469         len1 = 0;
1470 
1471     // if the input key data isn't a multiple of the blocksize,
1472     // we pad with NULLs to the next blocksize multiple.
1473     //
1474     if (len1 % DES_BLOCK_SIZE != 0) {
1475         len2 = DES_BLOCK_SIZE * ((len1 / DES_BLOCK_SIZE) + 1);
1476 
1477         if (length_only == FALSE) {
1478             /*
1479              * Don't use realloc here, since the buffer contains a key and the
1480              * old buffer needs to be cleansed before it is freed.
1481              */
1482             ptr = (CK_BYTE *)malloc(len2);
1483             if (!ptr) {
1484                 TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
1485                 return CKR_HOST_MEMORY;
1486             }
1487 
1488             memset(ptr + len1, 0x0, (len2 - len1));
1489             if (*data != NULL) {
1490                 memcpy(ptr, *data, len1);
1491                 OPENSSL_cleanse(*data, len1);
1492                 free(*data);
1493             }
1494 
1495             *data = ptr;
1496             *data_len = len2;
1497         }
1498     }
1499 
1500     return CKR_OK;
1501 }
1502