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 <pthread.h>
12 #include <string.h>             // for memcmp() et al
13 #include <stdlib.h>
14 
15 
16 #include "pkcs11types.h"
17 #include "defs.h"
18 #include "host_defs.h"
19 #include "h_extern.h"
20 #include "tok_spec_struct.h"
21 #include "trace.h"
22 
23 
24 // Permutation of 0..255 constructed from the digits of pi. It gives a
25 // "random" nonlinear byte substitution operation.
26 //
27 static CK_BYTE S[256] = {
28     41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
29     19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
30     76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
31     138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
32     245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
33     148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
34     39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
35     181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
36     150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
37     112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
38     96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
39     85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
40     234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
41     129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
42     8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
43     203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
44     166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
45     31, 26, 219, 153, 141, 51, 159, 17, 131, 20
46 };
47 
48 static CK_BYTE *padding[] = {
49     (CK_BYTE *) "",
50     (CK_BYTE *) "\x01",
51     (CK_BYTE *) "\x02\x02",
52     (CK_BYTE *) "\x03\x03\x03",
53     (CK_BYTE *) "\x04\x04\x04\x04",
54     (CK_BYTE *) "\x05\x05\x05\x05\x05",
55     (CK_BYTE *) "\x06\x06\x06\x06\x06\x06",
56     (CK_BYTE *) "\x07\x07\x07\x07\x07\x07\x07",
57     (CK_BYTE *) "\x08\x08\x08\x08\x08\x08\x08\x08",
58     (CK_BYTE *) "\x09\x09\x09\x09\x09\x09\x09\x09\x09",
59     (CK_BYTE *) "\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a",
60     (CK_BYTE *) "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
61     (CK_BYTE *) "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
62     (CK_BYTE *) "\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d\x0d",
63     (CK_BYTE *) "\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e",
64     (CK_BYTE *) "\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f",
65     (CK_BYTE *)
66         "\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10"
67 };
68 
69 
70 
71 //
72 //
md2_hash(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,DIGEST_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)73 CK_RV md2_hash(STDLL_TokData_t *tokdata,
74                SESSION *sess,
75                CK_BBOOL length_only,
76                DIGEST_CONTEXT *ctx,
77                CK_BYTE *in_data,
78                CK_ULONG in_data_len,
79                CK_BYTE *out_data, CK_ULONG *out_data_len)
80 {
81     CK_RV rc;
82 
83 
84     if (!sess || !ctx || !out_data_len) {
85         TRACE_ERROR("%s received bad argument(s)\n", __func__);
86         return CKR_FUNCTION_FAILED;
87     }
88 
89     if (length_only == TRUE) {
90         *out_data_len = MD2_HASH_SIZE;
91         return CKR_OK;
92     }
93 
94     if (*out_data_len < MD2_HASH_SIZE) {
95         *out_data_len = MD2_HASH_SIZE;
96         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
97         return CKR_BUFFER_TOO_SMALL;
98     }
99 
100     rc = md2_hash_update(tokdata, sess, ctx, in_data, in_data_len);
101     if (rc != CKR_OK) {
102         TRACE_DEVEL("md2_hash_update failed.\n");
103         return CKR_FUNCTION_FAILED;
104     }
105 
106     return md2_hash_final(tokdata, sess, FALSE, ctx, out_data, out_data_len);
107 }
108 
109 
110 //
111 //
md2_hash_update(STDLL_TokData_t * tokdata,SESSION * sess,DIGEST_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len)112 CK_RV md2_hash_update(STDLL_TokData_t *tokdata,
113                       SESSION *sess,
114                       DIGEST_CONTEXT *ctx,
115                       CK_BYTE *in_data, CK_ULONG in_data_len)
116 {
117     if (!sess || !ctx || !in_data) {
118         TRACE_ERROR("%s received bad argument(s)\n", __func__);
119         return CKR_FUNCTION_FAILED;
120     }
121 
122     return ckm_md2_update(tokdata, (MD2_CONTEXT *) ctx->context, in_data,
123                           in_data_len);
124 }
125 
126 
127 //
128 //
md2_hash_final(STDLL_TokData_t * tokdata,SESSION * sess,CK_BYTE length_only,DIGEST_CONTEXT * ctx,CK_BYTE * out_data,CK_ULONG * out_data_len)129 CK_RV md2_hash_final(STDLL_TokData_t *tokdata,
130                      SESSION *sess,
131                      CK_BYTE length_only,
132                      DIGEST_CONTEXT *ctx,
133                      CK_BYTE *out_data, CK_ULONG *out_data_len)
134 {
135     CK_RV rc;
136 
137     if (!sess || !ctx || !out_data_len) {
138         TRACE_ERROR("%s received bad argument(s)\n", __func__);
139         return CKR_FUNCTION_FAILED;
140     }
141     if (length_only == TRUE) {
142         *out_data_len = MD2_HASH_SIZE;
143         return CKR_OK;
144     }
145 
146     if (*out_data_len < MD2_HASH_SIZE) {
147         *out_data_len = MD2_HASH_SIZE;
148         TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
149         return CKR_BUFFER_TOO_SMALL;
150     }
151 
152     rc = ckm_md2_final(tokdata, (MD2_CONTEXT *) ctx->context,
153                        out_data, MD2_HASH_SIZE);
154 
155     if (rc == CKR_OK) {
156         *out_data_len = MD2_HASH_SIZE;
157         return rc;
158     }
159 
160     return rc;
161 }
162 
163 
164 // this routine gets called for two mechanisms actually:
165 //    CKM_MD2_HMAC
166 //    CKM_MD2_HMAC_GENERAL
167 //
md2_hmac_sign(STDLL_TokData_t * tokdata,SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)168 CK_RV md2_hmac_sign(STDLL_TokData_t *tokdata,
169                     SESSION *sess,
170                     CK_BBOOL length_only,
171                     SIGN_VERIFY_CONTEXT *ctx,
172                     CK_BYTE *in_data,
173                     CK_ULONG in_data_len,
174                     CK_BYTE *out_data, CK_ULONG *out_data_len)
175 {
176     OBJECT *key_obj = NULL;
177     CK_ATTRIBUTE *attr = NULL;
178     CK_BYTE hash[MD2_HASH_SIZE];
179     DIGEST_CONTEXT digest_ctx;
180     CK_MECHANISM digest_mech;
181     CK_BYTE k_ipad[MD2_BLOCK_SIZE];
182     CK_BYTE k_opad[MD2_BLOCK_SIZE];
183     CK_ULONG key_bytes, hash_len, hmac_len;
184     CK_ULONG i;
185     CK_RV rc;
186 
187 
188     if (!sess || !ctx || !out_data_len) {
189         TRACE_ERROR("%s received bad argument(s)\n", __func__);
190         return CKR_FUNCTION_FAILED;
191     }
192 
193     if (ctx->mech.mechanism == CKM_MD2_HMAC_GENERAL) {
194         hmac_len = *(CK_ULONG *) ctx->mech.pParameter;
195 
196         if (hmac_len == 0) {
197             *out_data_len = 0;
198             return CKR_OK;
199         }
200     } else {
201         hmac_len = MD2_HASH_SIZE;
202     }
203 
204 
205     if (length_only == TRUE) {
206         *out_data_len = hmac_len;
207         return CKR_OK;
208     }
209 
210     memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT));
211 
212     rc = object_mgr_find_in_map1(tokdata, ctx->key, &key_obj);
213     if (rc != CKR_OK) {
214         TRACE_ERROR("Failed to acquire key from specified handle");
215         if (rc == CKR_OBJECT_HANDLE_INVALID)
216             return CKR_KEY_HANDLE_INVALID;
217         else
218             return rc;
219     }
220     rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr);
221     if (rc == FALSE) {
222         TRACE_ERROR("Could not find CKA_VALUE in the template\n");
223         return CKR_FUNCTION_FAILED;
224     }
225 
226     key_bytes = attr->ulValueLen;
227 
228 
229     // build (K XOR ipad), (K XOR opad)
230     //
231     if (key_bytes > MD2_BLOCK_SIZE) {
232         digest_mech.mechanism = CKM_MD2;
233         digest_mech.ulParameterLen = 0;
234         digest_mech.pParameter = NULL;
235 
236         rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech);
237         if (rc != CKR_OK) {
238             TRACE_DEVEL("Digest Mgr Init failed.\n");
239             return rc;
240         }
241         hash_len = sizeof(hash);
242         rc = digest_mgr_digest(tokdata, sess, FALSE, &digest_ctx,
243                                attr->pValue, attr->ulValueLen, hash, &hash_len);
244         if (rc != CKR_OK) {
245             TRACE_DEVEL("Digest Mgr Digest failed.\n");
246             return rc;
247         }
248         memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT));
249 
250         for (i = 0; i < hash_len; i++) {
251             k_ipad[i] = hash[i] ^ 0x36;
252             k_opad[i] = hash[i] ^ 0x5C;
253         }
254 
255         memset(&k_ipad[i], 0x36, MD2_BLOCK_SIZE - i);
256         memset(&k_opad[i], 0x5C, MD2_BLOCK_SIZE - i);
257     } else {
258         CK_BYTE *key = (CK_BYTE *) attr + sizeof(CK_ATTRIBUTE);
259 
260         for (i = 0; i < key_bytes; i++) {
261             k_ipad[i] = key[i] ^ 0x36;
262             k_opad[i] = key[i] ^ 0x5C;
263         }
264 
265         memset(&k_ipad[i], 0x36, MD2_BLOCK_SIZE - key_bytes);
266         memset(&k_opad[i], 0x5C, MD2_BLOCK_SIZE - key_bytes);
267     }
268 
269     digest_mech.mechanism = CKM_MD2;
270     digest_mech.ulParameterLen = 0;
271     digest_mech.pParameter = NULL;
272 
273 
274     // inner hash
275     //
276     rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech);
277     if (rc != CKR_OK) {
278         TRACE_DEVEL("Digest Mgr Init failed.\n");
279         return rc;
280     }
281     rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_ipad,
282                                   MD2_BLOCK_SIZE);
283     if (rc != CKR_OK) {
284         TRACE_DEVEL("Digest Mgr Update failed.\n");
285         return rc;
286     }
287     rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, in_data,
288                                   in_data_len);
289     if (rc != CKR_OK) {
290         TRACE_DEVEL("Digest Mgr Update failed.\n");
291         return rc;
292     }
293     hash_len = sizeof(hash);
294     rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash,
295                                  &hash_len);
296     if (rc != CKR_OK) {
297         TRACE_DEVEL("Digest Mgr Final failed.\n");
298         return rc;
299     }
300     memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT));
301 
302 
303     // outer hash
304     //
305     rc = digest_mgr_init(tokdata, sess, &digest_ctx, &digest_mech);
306     if (rc != CKR_OK) {
307         TRACE_DEVEL("Digest Mgr Init failed.\n");
308         return rc;
309     }
310     rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, k_opad,
311                                   MD2_BLOCK_SIZE);
312     if (rc != CKR_OK) {
313         TRACE_DEVEL("Digest Mgr Update failed.\n");
314         return rc;
315     }
316     rc = digest_mgr_digest_update(tokdata, sess, &digest_ctx, hash, hash_len);
317     if (rc != CKR_OK) {
318         TRACE_DEVEL("Digest Mgr Update failed.\n");
319         return rc;
320     }
321     hash_len = sizeof(hash);
322     rc = digest_mgr_digest_final(tokdata, sess, FALSE, &digest_ctx, hash,
323                                  &hash_len);
324     if (rc != CKR_OK) {
325         TRACE_DEVEL("Digest Mgr Final failed.\n");
326         return rc;
327     }
328     memcpy(out_data, hash, hmac_len);
329     *out_data_len = hmac_len;
330 
331     return CKR_OK;
332 }
333 
334 
335 //
336 //
md2_hmac_verify(STDLL_TokData_t * tokdata,SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * signature,CK_ULONG sig_len)337 CK_RV md2_hmac_verify(STDLL_TokData_t *tokdata,
338                       SESSION *sess,
339                       SIGN_VERIFY_CONTEXT *ctx,
340                       CK_BYTE *in_data,
341                       CK_ULONG in_data_len,
342                       CK_BYTE *signature, CK_ULONG sig_len)
343 {
344     CK_BYTE hmac[MD2_HASH_SIZE];
345     SIGN_VERIFY_CONTEXT hmac_ctx;
346     CK_ULONG hmac_len, len;
347     CK_RV rc;
348 
349     if (!sess || !ctx || !in_data || !signature) {
350         TRACE_ERROR("%s received bad argument(s)\n", __func__);
351         return CKR_FUNCTION_FAILED;
352     }
353     if (ctx->mech.mechanism == CKM_MD2_HMAC_GENERAL)
354         hmac_len = *(CK_ULONG *) ctx->mech.pParameter;
355     else
356         hmac_len = MD2_HASH_SIZE;
357 
358     memset(&hmac_ctx, 0, sizeof(SIGN_VERIFY_CONTEXT));
359 
360     rc = sign_mgr_init(tokdata, sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key);
361     if (rc != CKR_OK) {
362         TRACE_DEVEL("Sign Mgr Init failed.\n");
363         return rc;
364     }
365     len = sizeof(hmac);
366     rc = sign_mgr_sign(tokdata, sess, FALSE, &hmac_ctx,
367                        in_data, in_data_len, hmac, &len);
368     if (rc != CKR_OK) {
369         TRACE_DEVEL("Sign Mgr Sign failed.\n");
370         return rc;
371     }
372     if ((len != hmac_len) || (len != sig_len)) {
373         TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_LEN_RANGE));
374         return CKR_SIGNATURE_LEN_RANGE;
375     }
376     if (memcmp(hmac, signature, hmac_len) != 0) {
377         TRACE_ERROR("%s\n", ock_err(ERR_SIGNATURE_INVALID));
378         return CKR_SIGNATURE_INVALID;
379     }
380 
381     return CKR_OK;
382 }
383 
384 
385 //
386 // CKM routines
387 //
388 
389 
390 // MD2 block update operation. Continues an MD2 message-digest
391 //   operation, processing another message block, and updating the
392 //   context.
393 //
ckm_md2_update(STDLL_TokData_t * tokdata,MD2_CONTEXT * context,CK_BYTE * input,CK_ULONG inputLen)394 CK_RV ckm_md2_update(STDLL_TokData_t *tokdata,
395                      MD2_CONTEXT *context, CK_BYTE *input, CK_ULONG inputLen)
396 {
397     CK_ULONG i, index, partLen;
398 
399     // Update number of bytes mod 16
400     //
401     index = context->count;
402     context->count = (index + inputLen) & 0xf;
403 
404     partLen = 16 - index;
405 
406     // Process any complete 16-byte blocks
407     //
408     if (inputLen >= partLen) {
409         memcpy((CK_BYTE *) & context->buffer[index], (CK_BYTE *) input,
410                partLen);
411         ckm_md2_transform(tokdata, context->state, context->checksum,
412                           context->buffer);
413 
414         for (i = partLen; i + 15 < inputLen; i += 16)
415             ckm_md2_transform(tokdata, context->state, context->checksum,
416                               &input[i]);
417 
418         index = 0;
419     } else {
420         i = 0;
421     }
422 
423     // Buffer remaining input
424     //
425     memcpy((CK_BYTE *) & context->buffer[index], (CK_BYTE *) & input[i],
426            inputLen - i);
427 
428     return CKR_OK;
429 }
430 
431 
432 // MD2 finalization. Ends an MD2 message-digest operation, writing the
433 //   message digest and zeroizing the context.
434 //
ckm_md2_final(STDLL_TokData_t * tokdata,MD2_CONTEXT * context,CK_BYTE * out_data,CK_ULONG out_data_len)435 CK_RV ckm_md2_final(STDLL_TokData_t *tokdata,
436                     MD2_CONTEXT *context,
437                     CK_BYTE *out_data, CK_ULONG out_data_len)
438 {
439     CK_ULONG index, padLen;
440 
441     if (!context || !out_data || (out_data_len < MD2_HASH_SIZE)) {
442         TRACE_ERROR("%s received bad argument(s)\n", __func__);
443         return CKR_FUNCTION_FAILED;
444     }
445     // Pad input to 16-byte multiple (1 - 16 pad bytes)
446     //
447     index = context->count;
448     padLen = 16 - index;
449     ckm_md2_update(tokdata, context, padding[padLen], padLen);
450 
451     // Add checksum
452     //
453     ckm_md2_update(tokdata, context, context->checksum, 16);
454 
455     // Store state in digest
456     //
457     memcpy((CK_BYTE *) out_data, (CK_BYTE *) context->state, 16);
458 
459     return CKR_OK;
460 }
461 
462 
463 // MD2 basic transformation. Transforms state and updates checksum
464 //   based on block.
465 //
ckm_md2_transform(STDLL_TokData_t * tokdata,CK_BYTE * state,CK_BYTE * checksum,CK_BYTE * block)466 void ckm_md2_transform(STDLL_TokData_t *tokdata,
467                        CK_BYTE *state, CK_BYTE *checksum, CK_BYTE *block)
468 {
469     CK_ULONG i, j, t;
470     CK_BYTE x[48];
471 
472     UNUSED(tokdata);
473 
474     // Form encryption block from state, block, state ^ block.
475     //
476     memcpy((CK_BYTE *) x, (CK_BYTE *) state, 16);
477     memcpy((CK_BYTE *) x + 16, (CK_BYTE *) block, 16);
478 
479     for (i = 0; i < 16; i++)
480         x[i + 32] = state[i] ^ block[i];
481 
482     // Encrypt block (18 rounds).
483     //
484     t = 0;
485     for (i = 0; i < 18; i++) {
486         for (j = 0; j < 48; j++)
487             t = x[j] ^= S[t];
488         t = (t + i) & 0xff;
489     }
490 
491     // Save new state
492     //
493     memcpy((CK_BYTE *) state, (CK_BYTE *) x, 16);
494 
495     // Update checksum.
496     //
497     t = checksum[15];
498     for (i = 0; i < 16; i++)
499         t = checksum[i] ^= S[block[i] ^ t];
500 
501 }
502