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 28 #include "tpmtok_int.h" 29 30 CK_RV 31 sign_mgr_init(SESSION * sess, 32 SIGN_VERIFY_CONTEXT * ctx, 33 CK_MECHANISM * mech, 34 CK_BBOOL recover_mode, 35 CK_OBJECT_HANDLE key) 36 { 37 OBJECT * key_obj = NULL; 38 CK_ATTRIBUTE * attr = NULL; 39 CK_BYTE * ptr = NULL; 40 CK_KEY_TYPE keytype; 41 CK_OBJECT_CLASS class; 42 CK_BBOOL flag; 43 CK_RV rc; 44 45 if (! sess || ! ctx) { 46 return (CKR_FUNCTION_FAILED); 47 } 48 if (ctx->active != FALSE) { 49 return (CKR_OPERATION_ACTIVE); 50 } 51 52 rc = object_mgr_find_in_map1(sess->hContext, key, &key_obj); 53 if (rc != CKR_OK) { 54 return (CKR_KEY_HANDLE_INVALID); 55 } 56 rc = template_attribute_find(key_obj->template, CKA_SIGN, &attr); 57 if (rc == FALSE) { 58 return (CKR_KEY_TYPE_INCONSISTENT); 59 } else { 60 flag = *(CK_BBOOL *)attr->pValue; 61 if (flag != TRUE) { 62 return (CKR_KEY_FUNCTION_NOT_PERMITTED); 63 } 64 } 65 66 switch (mech->mechanism) { 67 case CKM_RSA_PKCS: 68 { 69 rc = template_attribute_find(key_obj->template, 70 CKA_KEY_TYPE, &attr); 71 if (rc == FALSE) { 72 return (CKR_KEY_TYPE_INCONSISTENT); 73 } else { 74 keytype = *(CK_KEY_TYPE *)attr->pValue; 75 if (keytype != CKK_RSA) { 76 return (CKR_KEY_TYPE_INCONSISTENT); 77 } 78 } 79 80 // must be a PRIVATE key 81 // 82 flag = template_attribute_find(key_obj->template, 83 CKA_CLASS, &attr); 84 if (flag == FALSE) { 85 return (CKR_KEY_TYPE_INCONSISTENT); 86 } 87 else 88 class = *(CK_OBJECT_CLASS *)attr->pValue; 89 90 if (class != CKO_PRIVATE_KEY) { 91 return (CKR_KEY_TYPE_INCONSISTENT); 92 } 93 // PKCS #11 doesn't allow multi - part RSA operations 94 // 95 ctx->context_len = 0; 96 ctx->context = NULL; 97 } 98 break; 99 case CKM_MD5_RSA_PKCS: 100 case CKM_SHA1_RSA_PKCS: 101 { 102 rc = template_attribute_find(key_obj->template, 103 CKA_KEY_TYPE, &attr); 104 if (rc == FALSE) { 105 return (CKR_KEY_TYPE_INCONSISTENT); 106 } else { 107 keytype = *(CK_KEY_TYPE *)attr->pValue; 108 if (keytype != CKK_RSA) { 109 return (CKR_KEY_TYPE_INCONSISTENT); 110 } 111 } 112 113 // must be a PRIVATE key operation 114 // 115 flag = template_attribute_find(key_obj->template, 116 CKA_CLASS, &attr); 117 if (flag == FALSE) { 118 return (CKR_FUNCTION_FAILED); 119 } 120 else 121 class = *(CK_OBJECT_CLASS *)attr->pValue; 122 123 if (class != CKO_PRIVATE_KEY) { 124 return (CKR_FUNCTION_FAILED); 125 } 126 ctx->context_len = sizeof (RSA_DIGEST_CONTEXT); 127 ctx->context = (CK_BYTE *)malloc( 128 sizeof (RSA_DIGEST_CONTEXT)); 129 if (! ctx->context) { 130 return (CKR_HOST_MEMORY); 131 } 132 (void) memset(ctx->context, 0x0, 133 sizeof (RSA_DIGEST_CONTEXT)); 134 } 135 break; 136 case CKM_MD5_HMAC: 137 case CKM_SHA_1_HMAC: 138 { 139 if (mech->ulParameterLen != 0) { 140 return (CKR_MECHANISM_PARAM_INVALID); 141 } 142 rc = template_attribute_find(key_obj->template, 143 CKA_KEY_TYPE, &attr); 144 if (rc == FALSE) { 145 return (CKR_KEY_TYPE_INCONSISTENT); 146 } else { 147 keytype = *(CK_KEY_TYPE *)attr->pValue; 148 if (keytype != CKK_GENERIC_SECRET) { 149 return (CKR_KEY_TYPE_INCONSISTENT); 150 } 151 } 152 153 // PKCS #11 doesn't allow multi - part HMAC operations 154 // 155 ctx->context_len = 0; 156 ctx->context = NULL; 157 } 158 break; 159 160 case CKM_MD5_HMAC_GENERAL: 161 case CKM_SHA_1_HMAC_GENERAL: 162 { 163 CK_MAC_GENERAL_PARAMS *param = 164 (CK_MAC_GENERAL_PARAMS *)mech->pParameter; 165 166 if (mech->ulParameterLen != 167 sizeof (CK_MAC_GENERAL_PARAMS)) { 168 return (CKR_MECHANISM_PARAM_INVALID); 169 } 170 171 if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) && 172 (*param > 16)) { 173 return (CKR_MECHANISM_PARAM_INVALID); 174 } 175 if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) && 176 (*param > 20)) { 177 return (CKR_MECHANISM_PARAM_INVALID); 178 } 179 rc = template_attribute_find(key_obj->template, 180 CKA_KEY_TYPE, &attr); 181 if (rc == FALSE) { 182 return (CKR_KEY_TYPE_INCONSISTENT); 183 } else { 184 keytype = *(CK_KEY_TYPE *)attr->pValue; 185 if (keytype != CKK_GENERIC_SECRET) { 186 return (CKR_KEY_TYPE_INCONSISTENT); 187 } 188 } 189 190 // PKCS #11 doesn't allow multi - part HMAC operations 191 // 192 ctx->context_len = 0; 193 ctx->context = NULL; 194 } 195 break; 196 default: 197 return (CKR_MECHANISM_INVALID); 198 } 199 200 if (mech->ulParameterLen > 0 && mech->pParameter == NULL) 201 return (CKR_ARGUMENTS_BAD); 202 203 if (mech->ulParameterLen > 0) { 204 ptr = (CK_BYTE *)malloc(mech->ulParameterLen); 205 if (! ptr) { 206 return (CKR_HOST_MEMORY); 207 } 208 (void) memcpy(ptr, mech->pParameter, mech->ulParameterLen); 209 } 210 211 ctx->key = key; 212 ctx->mech.ulParameterLen = mech->ulParameterLen; 213 ctx->mech.mechanism = mech->mechanism; 214 ctx->mech.pParameter = ptr; 215 ctx->multi = FALSE; 216 ctx->active = TRUE; 217 ctx->recover = recover_mode; 218 219 return (CKR_OK); 220 } 221 222 CK_RV 223 sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx) 224 { 225 if (! ctx) { 226 return (CKR_FUNCTION_FAILED); 227 } 228 ctx->key = 0; 229 ctx->mech.ulParameterLen = 0; 230 ctx->mech.mechanism = 0; 231 ctx->multi = FALSE; 232 ctx->active = FALSE; 233 ctx->recover = FALSE; 234 ctx->context_len = 0; 235 236 if (ctx->mech.pParameter) { 237 free(ctx->mech.pParameter); 238 ctx->mech.pParameter = NULL; 239 } 240 241 if (ctx->context) { 242 free(ctx->context); 243 ctx->context = NULL; 244 } 245 246 return (CKR_OK); 247 } 248 249 CK_RV 250 sign_mgr_sign(SESSION * sess, 251 CK_BBOOL length_only, 252 SIGN_VERIFY_CONTEXT * ctx, 253 CK_BYTE * in_data, 254 CK_ULONG in_data_len, 255 CK_BYTE * out_data, 256 CK_ULONG * out_data_len) 257 { 258 if (! sess || ! ctx) { 259 return (CKR_FUNCTION_FAILED); 260 } 261 if (ctx->active == FALSE) { 262 return (CKR_OPERATION_NOT_INITIALIZED); 263 } 264 if (ctx->recover == TRUE) { 265 return (CKR_OPERATION_NOT_INITIALIZED); 266 } 267 268 // if the caller just wants the signature length, there is no reason to 269 // specify the input data. I just need the input data length 270 // 271 if ((length_only == FALSE) && (! in_data || ! out_data)) { 272 return (CKR_FUNCTION_FAILED); 273 } 274 if (ctx->multi == TRUE) { 275 return (CKR_OPERATION_ACTIVE); 276 } 277 switch (ctx->mech.mechanism) { 278 case CKM_RSA_PKCS: 279 return (rsa_pkcs_sign(sess, length_only, ctx, 280 in_data, in_data_len, 281 out_data, out_data_len)); 282 case CKM_MD5_RSA_PKCS: 283 case CKM_SHA1_RSA_PKCS: 284 return (rsa_hash_pkcs_sign(sess, length_only, ctx, 285 in_data, in_data_len, 286 out_data, out_data_len)); 287 288 case CKM_MD5_HMAC: 289 case CKM_MD5_HMAC_GENERAL: 290 return (md5_hmac_sign(sess, length_only, ctx, 291 in_data, in_data_len, 292 out_data, out_data_len)); 293 case CKM_SHA_1_HMAC: 294 case CKM_SHA_1_HMAC_GENERAL: 295 return (sha1_hmac_sign(sess, length_only, ctx, 296 in_data, in_data_len, 297 out_data, out_data_len)); 298 default: 299 return (CKR_MECHANISM_INVALID); 300 } 301 } 302 303 CK_RV 304 sign_mgr_sign_update(SESSION * sess, 305 SIGN_VERIFY_CONTEXT * ctx, 306 CK_BYTE * in_data, 307 CK_ULONG in_data_len) 308 { 309 if (! sess || ! ctx || ! in_data) { 310 return (CKR_FUNCTION_FAILED); 311 } 312 313 if (ctx->active == FALSE) { 314 return (CKR_OPERATION_NOT_INITIALIZED); 315 } 316 if (ctx->recover == TRUE) { 317 return (CKR_OPERATION_NOT_INITIALIZED); 318 } 319 ctx->multi = TRUE; 320 321 switch (ctx->mech.mechanism) { 322 case CKM_MD5_RSA_PKCS: 323 case CKM_SHA1_RSA_PKCS: 324 return (rsa_hash_pkcs_sign_update(sess, ctx, 325 in_data, in_data_len)); 326 default: 327 return (CKR_MECHANISM_INVALID); 328 } 329 } 330 331 CK_RV 332 sign_mgr_sign_final(SESSION * sess, 333 CK_BBOOL length_only, 334 SIGN_VERIFY_CONTEXT * ctx, 335 CK_BYTE * signature, 336 CK_ULONG * sig_len) 337 { 338 if (! sess || ! ctx) { 339 return (CKR_FUNCTION_FAILED); 340 } 341 if (ctx->active == FALSE) { 342 return (CKR_OPERATION_NOT_INITIALIZED); 343 } 344 if (ctx->recover == TRUE) { 345 return (CKR_OPERATION_NOT_INITIALIZED); 346 } 347 switch (ctx->mech.mechanism) { 348 case CKM_MD5_RSA_PKCS: 349 case CKM_SHA1_RSA_PKCS: 350 return (rsa_hash_pkcs_sign_final(sess, length_only, 351 ctx, signature, sig_len)); 352 default: 353 return (CKR_MECHANISM_INVALID); 354 } 355 } 356 357 CK_RV 358 sign_mgr_sign_recover(SESSION * sess, 359 CK_BBOOL length_only, 360 SIGN_VERIFY_CONTEXT * ctx, 361 CK_BYTE * in_data, 362 CK_ULONG in_data_len, 363 CK_BYTE * out_data, 364 CK_ULONG * out_data_len) 365 { 366 if (! sess || ! ctx) { 367 return (CKR_FUNCTION_FAILED); 368 } 369 if (ctx->active == FALSE) { 370 return (CKR_OPERATION_NOT_INITIALIZED); 371 } 372 if (ctx->recover == FALSE) { 373 return (CKR_OPERATION_NOT_INITIALIZED); 374 } 375 376 // if the caller just wants the signature length, there is no reason to 377 // specify the input data. I just need the input data length 378 // 379 if ((length_only == FALSE) && (! in_data || ! out_data)) { 380 return (CKR_FUNCTION_FAILED); 381 } 382 if (ctx->multi == TRUE) { 383 return (CKR_OPERATION_ACTIVE); 384 } 385 switch (ctx->mech.mechanism) { 386 case CKM_RSA_PKCS: 387 return (rsa_pkcs_sign(sess, length_only, ctx, 388 in_data, in_data_len, 389 out_data, out_data_len)); 390 default: 391 return (CKR_MECHANISM_INVALID); 392 } 393 } 394