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