1/* 2 * Copyright (c) 2000-2001,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18 19/* 20 * FEESignatureObject.cpp - implementations of FEE-style raw sign/verify classes 21 * 22 */ 23 24#ifdef CRYPTKIT_CSP_ENABLE 25 26#include "FEESignatureObject.h" 27#include <security_cryptkit/feePublicKey.h> 28#include <security_cryptkit/feeDigitalSignature.h> 29#include <security_cryptkit/falloc.h> 30#include <stdexcept> 31#include <assert.h> 32#include <security_utilities/debugging.h> 33 34#define feeSigObjDebug(args...) secdebug("feeSig", ##args) 35 36CryptKit::FEESigner::~FEESigner() 37{ 38 if(mWeMallocdFeeKey) { 39 assert(mFeeKey != NULL); 40 feePubKeyFree(mFeeKey); 41 } 42} 43 44/* 45 * obtain key from context, validate, convert to native FEE key 46 */ 47void CryptKit::FEESigner::keyFromContext( 48 const Context &context) 49{ 50 if(initFlag() && (mFeeKey != NULL)) { 51 /* reusing context, OK */ 52 return; 53 } 54 55 CSSM_KEYCLASS keyClass; 56 CSSM_KEYUSE keyUse; 57 if(isSigning()) { 58 /* signing with private key */ 59 keyClass = CSSM_KEYCLASS_PRIVATE_KEY; 60 keyUse = CSSM_KEYUSE_SIGN; 61 } 62 else { 63 /* verifying with public key */ 64 keyClass = CSSM_KEYCLASS_PUBLIC_KEY; 65 keyUse = CSSM_KEYUSE_VERIFY; 66 } 67 if(mFeeKey == NULL) { 68 mFeeKey = contextToFeeKey(context, 69 mSession, 70 CSSM_ATTRIBUTE_KEY, 71 keyClass, 72 keyUse, 73 mWeMallocdFeeKey); 74 } 75} 76 77/* reusable init */ 78void CryptKit::FEESigner::signerInit( 79 const Context &context, 80 bool isSigning) 81{ 82 setIsSigning(isSigning); 83 keyFromContext(context); 84 setInitFlag(true); 85} 86 87/* 88 * Note that, unlike the implementation in security_cryptkit/feePublicKey.c, we ignore 89 * the Pm which used to be used as salt for the digest. That made staged verification 90 * impossible and I do not believe it increased security. 91 */ 92void CryptKit::FEERawSigner::sign( 93 const void *data, 94 size_t dataLen, 95 void *sig, 96 size_t *sigLen) /* IN/OUT */ 97{ 98 feeSig fsig; 99 feeReturn frtn; 100 unsigned char *feeSig; 101 unsigned feeSigLen=0; 102 103 if(mFeeKey == NULL) { 104 throwCryptKit(FR_BadPubKey, "FEERawSigner::sign (no key)"); 105 } 106 fsig = feeSigNewWithKey(mFeeKey, mRandFcn, mRandRef); 107 if(fsig == NULL) { 108 throwCryptKit(FR_BadPubKey, "FEERawSigner::sign"); 109 } 110 frtn = feeSigSign(fsig, 111 (unsigned char *)data, 112 (unsigned)dataLen, 113 mFeeKey); 114 if(frtn == FR_Success) { 115 frtn = feeSigData(fsig, &feeSig, &feeSigLen); 116 } 117 feeSigFree(fsig); 118 if(frtn) { 119 throwCryptKit(frtn, "FEERawSigner::sign"); 120 } 121 122 /* copy out to caller and ffree */ 123 if(*sigLen < feeSigLen) { 124 feeSigObjDebug("FEERawSigner sign overflow\n"); 125 ffree(feeSig); 126 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); 127 } 128 memmove(sig, feeSig, feeSigLen); 129 *sigLen = feeSigLen; 130 ffree(feeSig); 131} 132 133void CryptKit::FEERawSigner::verify( 134 const void *data, 135 size_t dataLen, 136 const void *sig, 137 size_t sigLen) 138{ 139 feeSig fsig; 140 feeReturn frtn; 141 142 if(mFeeKey == NULL) { 143 throwCryptKit(FR_BadPubKey, "FEERawSigner::verify (no key)"); 144 } 145 frtn = feeSigParse((unsigned char *)sig, sigLen, &fsig); 146 if(frtn) { 147 throwCryptKit(frtn, "feeSigParse"); 148 } 149 frtn = feeSigVerify(fsig, 150 (unsigned char *)data, 151 (unsigned int)dataLen, 152 mFeeKey); 153 feeSigFree(fsig); 154 if(frtn) { 155 throwCryptKit(frtn, NULL); 156 } 157} 158 159size_t CryptKit::FEERawSigner::maxSigSize() 160{ 161 unsigned rtn; 162 feeReturn frtn; 163 164 frtn = feeSigSize(mFeeKey, &rtn); 165 if(frtn) { 166 throwCryptKit(frtn, "feeSigSize"); 167 } 168 return rtn; 169} 170 171/* ECDSA - this is really easy. */ 172 173void CryptKit::FEEECDSASigner::sign( 174 const void *data, 175 size_t dataLen, 176 void *sig, 177 size_t *sigLen) /* IN/OUT */ 178{ 179 unsigned char *feeSig; 180 unsigned feeSigLen; 181 feeReturn frtn; 182 183 if(mFeeKey == NULL) { 184 throwCryptKit(FR_BadPubKey, "FEERawSigner::sign (no key)"); 185 } 186 frtn = feeECDSASign(mFeeKey, 187 (unsigned char *)data, // data to be signed 188 (unsigned int)dataLen, // in bytes 189 mRandFcn, 190 mRandRef, 191 &feeSig, 192 &feeSigLen); 193 if(frtn) { 194 throwCryptKit(frtn, "feeECDSASign"); 195 } 196 /* copy out to caller and ffree */ 197 if(*sigLen < feeSigLen) { 198 feeSigObjDebug("feeECDSASign overflow\n"); 199 ffree(feeSig); 200 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); 201 } 202 memmove(sig, feeSig, feeSigLen); 203 *sigLen = feeSigLen; 204 ffree(feeSig); 205 206} 207 208void CryptKit::FEEECDSASigner::verify( 209 const void *data, 210 size_t dataLen, 211 const void *sig, 212 size_t sigLen) 213{ 214 feeReturn frtn; 215 216 if(mFeeKey == NULL) { 217 throwCryptKit(FR_BadPubKey, "FEERawSigner::verify (no key)"); 218 } 219 frtn = feeECDSAVerify((unsigned char *)sig, 220 sigLen, 221 (unsigned char *)data, 222 (unsigned int)dataLen, 223 mFeeKey); 224 if(frtn) { 225 throwCryptKit(frtn, NULL); 226 } 227} 228 229size_t CryptKit::FEEECDSASigner::maxSigSize() 230{ 231 unsigned rtn; 232 feeReturn frtn; 233 234 frtn = feeECDSASigSize(mFeeKey, &rtn); 235 if(frtn) { 236 throwCryptKit(frtn, "feeECDSASigSize"); 237 } 238 return rtn; 239} 240 241#endif /* CRYPTKIT_CSP_ENABLE */ 242