1 /* 2 * The Initial Developer of the Original Code is International 3 * Business Machines Corporation. Portions created by IBM 4 * Corporation are Copyright (C) 2005 International Business 5 * Machines Corporation. All Rights Reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the Common Public License as published by 9 * IBM Corporation; either version 1 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * Common Public License for more details. 16 * 17 * You should have received a copy of the Common Public License 18 * along with this program; if not, a copy can be viewed at 19 * http://www.opensource.org/licenses/cpl1.0.php. 20 */ 21 22 /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ 23 /* 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 #include "tpmtok_int.h" 28 29 CK_RV 30 sha1_hash(SESSION *sess, 31 CK_BBOOL length_only, 32 DIGEST_CONTEXT *ctx, 33 CK_BYTE *in_data, 34 CK_ULONG in_data_len, 35 CK_BYTE *out_data, 36 CK_ULONG *out_data_len) 37 { 38 if (! sess || ! ctx || ! out_data_len) { 39 return (CKR_FUNCTION_FAILED); 40 } 41 *out_data_len = SHA1_DIGEST_LENGTH; 42 if (length_only == TRUE) { 43 return (CKR_OK); 44 } 45 46 if (ctx->context.sha1ctx == NULL) 47 return (CKR_HOST_MEMORY); 48 SHA1Update(ctx->context.sha1ctx, in_data, in_data_len); 49 50 SHA1Final(out_data, ctx->context.sha1ctx); 51 52 return (CKR_OK); 53 } 54 55 CK_RV 56 sha1_hmac_sign(SESSION * sess, 57 CK_BBOOL length_only, 58 SIGN_VERIFY_CONTEXT * ctx, 59 CK_BYTE * in_data, 60 CK_ULONG in_data_len, 61 CK_BYTE * out_data, 62 CK_ULONG * out_data_len) { 63 OBJECT * key_obj = NULL; 64 CK_ATTRIBUTE * attr = NULL; 65 CK_BYTE hash[SHA1_DIGEST_LENGTH]; 66 DIGEST_CONTEXT digest_ctx; 67 CK_MECHANISM digest_mech; 68 CK_BYTE k_ipad[SHA1_BLOCK_SIZE]; 69 CK_BYTE k_opad[SHA1_BLOCK_SIZE]; 70 CK_ULONG key_bytes, hash_len, hmac_len; 71 CK_ULONG i; 72 CK_RV rc; 73 74 if (! sess || ! ctx || ! out_data_len) { 75 return (CKR_FUNCTION_FAILED); 76 } 77 78 if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL) { 79 hmac_len = *(CK_ULONG *)ctx->mech.pParameter; 80 81 if (hmac_len == 0) { 82 *out_data_len = 0; 83 return (CKR_OK); 84 } 85 } else { 86 hmac_len = SHA1_DIGEST_LENGTH; 87 } 88 89 *out_data_len = hmac_len; 90 if (length_only == TRUE) { 91 return (CKR_OK); 92 } 93 94 (void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT)); 95 96 rc = object_mgr_find_in_map1(sess->hContext, ctx->key, &key_obj); 97 if (rc != CKR_OK) { 98 return (rc); 99 } 100 rc = template_attribute_find(key_obj->template, CKA_VALUE, &attr); 101 if (rc == FALSE) { 102 return (CKR_FUNCTION_FAILED); 103 } else 104 key_bytes = attr->ulValueLen; 105 106 107 if (key_bytes > SHA1_BLOCK_SIZE) { 108 digest_mech.mechanism = CKM_SHA_1; 109 digest_mech.ulParameterLen = 0; 110 digest_mech.pParameter = NULL; 111 112 rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); 113 if (rc != CKR_OK) { 114 (void) digest_mgr_cleanup(&digest_ctx); 115 return (rc); 116 } 117 118 hash_len = sizeof (hash); 119 rc = digest_mgr_digest(sess, FALSE, &digest_ctx, 120 attr->pValue, attr->ulValueLen, hash, &hash_len); 121 if (rc != CKR_OK) { 122 (void) digest_mgr_cleanup(&digest_ctx); 123 return (rc); 124 } 125 126 (void) digest_mgr_cleanup(&digest_ctx); 127 (void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT)); 128 129 for (i = 0; i < hash_len; i++) { 130 k_ipad[i] = hash[i] ^ 0x36; 131 k_opad[i] = hash[i] ^ 0x5C; 132 } 133 134 (void) memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - i); 135 (void) memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - i); 136 } else { 137 CK_BYTE *key = attr->pValue; 138 139 for (i = 0; i < key_bytes; i++) { 140 k_ipad[i] = key[i] ^ 0x36; 141 k_opad[i] = key[i] ^ 0x5C; 142 } 143 144 (void) memset(&k_ipad[i], 0x36, SHA1_BLOCK_SIZE - key_bytes); 145 (void) memset(&k_opad[i], 0x5C, SHA1_BLOCK_SIZE - key_bytes); 146 } 147 148 digest_mech.mechanism = CKM_SHA_1; 149 digest_mech.ulParameterLen = 0; 150 digest_mech.pParameter = NULL; 151 152 if (rc != CKR_OK) { 153 (void) digest_mgr_cleanup(&digest_ctx); 154 return (rc); 155 } 156 157 rc = digest_mgr_digest_update(sess, &digest_ctx, 158 k_ipad, SHA1_BLOCK_SIZE); 159 if (rc != CKR_OK) { 160 (void) digest_mgr_cleanup(&digest_ctx); 161 return (rc); 162 } 163 164 rc = digest_mgr_digest_update(sess, &digest_ctx, in_data, in_data_len); 165 if (rc != CKR_OK) { 166 (void) digest_mgr_cleanup(&digest_ctx); 167 return (rc); 168 } 169 170 hash_len = sizeof (hash); 171 rc = digest_mgr_digest_final(sess, &digest_ctx, hash, &hash_len); 172 if (rc != CKR_OK) { 173 (void) digest_mgr_cleanup(&digest_ctx); 174 return (rc); 175 } 176 177 (void) digest_mgr_cleanup(&digest_ctx); 178 (void) memset(&digest_ctx, 0x0, sizeof (DIGEST_CONTEXT)); 179 180 rc = digest_mgr_init(sess, &digest_ctx, &digest_mech); 181 if (rc != CKR_OK) { 182 (void) digest_mgr_cleanup(&digest_ctx); 183 return (rc); 184 } 185 186 rc = digest_mgr_digest_update(sess, &digest_ctx, 187 k_opad, SHA1_BLOCK_SIZE); 188 if (rc != CKR_OK) { 189 (void) digest_mgr_cleanup(&digest_ctx); 190 return (rc); 191 } 192 193 rc = digest_mgr_digest_update(sess, &digest_ctx, hash, hash_len); 194 if (rc != CKR_OK) { 195 (void) digest_mgr_cleanup(&digest_ctx); 196 return (rc); 197 } 198 199 hash_len = sizeof (hash); 200 rc = digest_mgr_digest_final(sess, &digest_ctx, hash, &hash_len); 201 if (rc != CKR_OK) { 202 (void) digest_mgr_cleanup(&digest_ctx); 203 return (rc); 204 } 205 206 (void) memcpy(out_data, hash, hmac_len); 207 *out_data_len = hmac_len; 208 209 (void) digest_mgr_cleanup(&digest_ctx); 210 211 return (CKR_OK); 212 } 213 214 CK_RV 215 sha1_hmac_verify(SESSION *sess, 216 SIGN_VERIFY_CONTEXT *ctx, 217 CK_BYTE *in_data, 218 CK_ULONG in_data_len, 219 CK_BYTE *signature, 220 CK_ULONG sig_len) 221 { 222 CK_BYTE hmac[SHA1_DIGEST_LENGTH]; 223 SIGN_VERIFY_CONTEXT hmac_ctx; 224 CK_ULONG hmac_len, len; 225 CK_RV rc; 226 227 if (! sess || ! ctx || ! in_data || ! signature) { 228 return (CKR_FUNCTION_FAILED); 229 } 230 if (ctx->mech.mechanism == CKM_SHA_1_HMAC_GENERAL) 231 hmac_len = *(CK_ULONG *)ctx->mech.pParameter; 232 else 233 hmac_len = SHA1_DIGEST_LENGTH; 234 235 (void) memset(&hmac_ctx, 0, sizeof (SIGN_VERIFY_CONTEXT)); 236 237 rc = sign_mgr_init(sess, &hmac_ctx, &ctx->mech, FALSE, ctx->key); 238 if (rc != CKR_OK) { 239 goto done; 240 } 241 len = sizeof (hmac); 242 rc = sign_mgr_sign(sess, FALSE, &hmac_ctx, 243 in_data, in_data_len, hmac, &len); 244 if (rc != CKR_OK) { 245 goto done; 246 } 247 if ((len != hmac_len) || (len != sig_len)) { 248 rc = CKR_SIGNATURE_LEN_RANGE; 249 goto done; 250 } 251 252 if (memcmp(hmac, signature, hmac_len) != 0) { 253 rc = CKR_SIGNATURE_INVALID; 254 } 255 done: 256 (void) sign_mgr_cleanup(&hmac_ctx); 257 return (rc); 258 } 259