/* * Sign/verify wrappers. */ static CSSM_RETURN sigSign(CSSM_CSP_HANDLE cspHandle, uint32 algorithm, // CSSM_ALGID_SHA1WithRSA, etc. CSSM_KEY_PTR key, // private key const CSSM_DATA *text, CSSM_DATA_PTR sig) { CSSM_CC_HANDLE sigHand; CSSM_RETURN crtn; crtn = CSSM_CSP_CreateSignatureContext(cspHandle, algorithm, NULL, // passPhrase key, &sigHand); if(crtn) { return crtn; } crtn = CSSM_SignData(sigHand, text, 1, CSSM_ALGID_NONE, sig); CSSM_DeleteContext(sigHand); return crtn; }
static int kc_rsa_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { struct kc_rsa *kc = RSA_get_app_data(rsa); CSSM_RETURN cret; OSStatus ret; const CSSM_ACCESS_CREDENTIALS *creds; SecKeyRef privKeyRef = (SecKeyRef)kc->item; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; CSSM_CC_HANDLE sigHandle = 0; CSSM_DATA sig, in; int fret = 0; if (padding != RSA_PKCS1_PADDING) return -1; cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); if(cret) abort(); cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); if(cret) abort(); ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &creds); if(ret) abort(); ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, creds, cssmKey, &sigHandle); if(ret) abort(); in.Data = (uint8 *)from; in.Length = flen; sig.Data = (uint8 *)to; sig.Length = kc->keysize; cret = CSSM_SignData(sigHandle, &in, 1, CSSM_ALGID_NONE, &sig); if(cret) { /* cssmErrorString(cret); */ fret = -1; } else fret = sig.Length; if(sigHandle) CSSM_DeleteContext(sigHandle); return fret; }
static int doSign( CSSM_CSP_HANDLE cspHand, const char *algStr, CSSM_KEY_PTR key, // private CSSM_ALGORITHMS sigAlg, CSSM_RETURN expRtn, // expected result CSSM_BOOL quiet) { uint8 ptextData[PTEXT_SIZE]; CSSM_DATA ptext = {PTEXT_SIZE, ptextData}; CSSM_DATA sig = {0, NULL}; simpleGenData(&ptext, PTEXT_SIZE, PTEXT_SIZE); CSSM_CC_HANDLE cryptHand = 0; CSSM_RETURN crtn; crtn = CSSM_CSP_CreateSignatureContext(cspHand, sigAlg, NULL, // passPhrase key, &cryptHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext (1)", crtn); return testError(quiet); } int irtn = 0; crtn = CSSM_SignData(cryptHand, &ptext, 1, CSSM_ALGID_NONE, &sig); if(crtn != expRtn) { if(expRtn == CSSM_OK) { printError("CSSM_SignData", crtn); printf("Unexpected error signing with %s\n", algStr); } else { printf("***Sign with %s: expected %s, got %s.\n", algStr, cssmErrToStr(expRtn), cssmErrToStr(crtn)); } irtn = testError(quiet); } appFreeCssmData(&sig, CSSM_FALSE); CSSM_DeleteContext(cryptHand); return irtn; }
/* * Sign/verify optional "no padding" context attr */ static CSSM_RETURN sigSign(CSSM_CSP_HANDLE cspHand, uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. CSSM_KEY_PTR key, // private key const CSSM_DATA *text, CSSM_DATA_PTR sig, uint32 digestAlg, // optional for raw signing CSSM_BOOL noPad) // true --> add PADDING_NONE to context { CSSM_CC_HANDLE sigHand; CSSM_RETURN crtn; crtn = CSSM_CSP_CreateSignatureContext(cspHand, algorithm, NULL, // passPhrase key, &sigHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext", crtn); return crtn; } if(noPad) { crtn = AddContextAttribute(sigHand, CSSM_ATTRIBUTE_PADDING, sizeof(uint32), CAT_Uint32, NULL, CSSM_PADDING_NONE); if(crtn) { return crtn; } } crtn = CSSM_SignData(sigHand, text, 1, digestAlg, sig); if(crtn) { printError("CSSM_SignData", crtn); } CSSM_DeleteContext(sigHand); return crtn; }
SECStatus ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, PRBool isTLS, KeyType keyType) { SECStatus rv = SECFailure; PRBool doDerEncode = PR_FALSE; unsigned int signatureLen; OSStatus status = noErr; CSSM_CSP_HANDLE cspHandle = 0; const CSSM_KEY *cssmKey = NULL; CSSM_ALGORITHMS sigAlg; CSSM_ALGORITHMS digestAlg; const CSSM_ACCESS_CREDENTIALS * cssmCreds = NULL; CSSM_RETURN cssmRv; CSSM_DATA hashData; CSSM_DATA signatureData; CSSM_CC_HANDLE cssmSignature = 0; const SSL3Opaque* prefix; unsigned int prefixLen; SSL3Opaque prefixAndHash[SSL_MAX_DIGEST_INFO_PREFIX + HASH_LENGTH_MAX]; buf->data = NULL; status = SecKeyGetCSPHandle(key, &cspHandle); if (status != noErr) { PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } status = SecKeyGetCSSMKey(key, &cssmKey); if (status != noErr || !cssmKey) { PORT_SetError(SEC_ERROR_NO_KEY); goto done; } /* SecKeyGetBlockSize wasn't addeded until OS X 10.6 - but the * needed information is readily available on the key itself. */ signatureLen = (cssmKey->KeyHeader.LogicalKeySizeInBits + 7) / 8; if (signatureLen == 0) { PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } buf->data = (unsigned char *)PORT_Alloc(signatureLen); if (!buf->data) goto done; /* error code was set. */ sigAlg = cssmKey->KeyHeader.AlgorithmId; digestAlg = CSSM_ALGID_NONE; switch (keyType) { case rsaKey: PORT_Assert(sigAlg == CSSM_ALGID_RSA); if (ssl3_GetDigestInfoPrefix(hash->hashAlg, &prefix, &prefixLen) != SECSuccess) { goto done; } if (prefixLen + hash->len > sizeof(prefixAndHash)) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); goto done; } memcpy(prefixAndHash, prefix, prefixLen); memcpy(prefixAndHash + prefixLen, hash->u.raw, hash->len); hashData.Data = prefixAndHash; hashData.Length = prefixLen + hash->len; break; case dsaKey: case ecKey: if (keyType == ecKey) { PORT_Assert(sigAlg == CSSM_ALGID_ECDSA); doDerEncode = PR_TRUE; } else { PORT_Assert(sigAlg == CSSM_ALGID_DSA); doDerEncode = isTLS; } if (hash->hashAlg == SEC_OID_UNKNOWN) { hashData.Data = hash->u.s.sha; hashData.Length = sizeof(hash->u.s.sha); } else { hashData.Data = hash->u.raw; hashData.Length = hash->len; } break; default: PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } PRINT_BUF(60, (NULL, "hash(es) to be signed", hashData.Data, hashData.Length)); /* TODO(rsleevi): Should it be kSecCredentialTypeNoUI? In Win32, at least, * you can prevent the UI by setting the provider handle on the * certificate to be opened with CRYPT_SILENT, but is there an equivalent? */ status = SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &cssmCreds); if (status != noErr) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, status); goto done; } signatureData.Length = signatureLen; signatureData.Data = (uint8*)buf->data; cssmRv = CSSM_CSP_CreateSignatureContext(cspHandle, sigAlg, cssmCreds, cssmKey, &cssmSignature); if (cssmRv) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); goto done; } /* See "Apple Cryptographic Service Provider Functional Specification" */ if (cssmKey->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) { /* To set RSA blinding for RSA keys */ CSSM_CONTEXT_ATTRIBUTE blindingAttr; blindingAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; blindingAttr.AttributeLength = sizeof(uint32); blindingAttr.Attribute.Uint32 = 1; cssmRv = CSSM_UpdateContextAttributes(cssmSignature, 1, &blindingAttr); if (cssmRv) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); goto done; } } cssmRv = CSSM_SignData(cssmSignature, &hashData, 1, digestAlg, &signatureData); if (cssmRv) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); goto done; } buf->len = signatureData.Length; if (doDerEncode) { SECItem derSig = {siBuffer, NULL, 0}; /* This also works for an ECDSA signature */ rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len); if (rv == SECSuccess) { PORT_Free(buf->data); /* discard unencoded signature. */ *buf = derSig; /* give caller encoded signature. */ } else if (derSig.data) { PORT_Free(derSig.data); } } else { rv = SECSuccess; } PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); done: /* cspHandle, cssmKey, and cssmCreds are owned by the SecKeyRef and * should not be freed. When the PlatformKey is freed, they will be * released. */ if (cssmSignature) CSSM_DeleteContext(cssmSignature); if (rv != SECSuccess && buf->data) { PORT_Free(buf->data); buf->data = NULL; } return rv; }
static int kc_rsa_sign(int type, const unsigned char *from, unsigned int flen, unsigned char *to, unsigned int *tlen, const RSA *rsa) { struct kc_rsa *kc = RSA_get_app_data(rk_UNCONST(rsa)); CSSM_RETURN cret; OSStatus ret; const CSSM_ACCESS_CREDENTIALS *creds; SecKeyRef privKeyRef = kc->pkey; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; CSSM_CC_HANDLE sigHandle = 0; CSSM_DATA sig, in; int fret = 0; CSSM_ALGORITHMS stype; if (type == NID_md5) { stype = CSSM_ALGID_MD5; } else if (type == NID_sha1) { stype = CSSM_ALGID_SHA1; } else if (type == NID_sha256) { stype = CSSM_ALGID_SHA256; } else if (type == NID_sha384) { stype = CSSM_ALGID_SHA384; } else if (type == NID_sha512) { stype = CSSM_ALGID_SHA512; } else return -1; cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); if(cret) heim_abort("SecKeyGetCSSMKey failed: %d", cret); cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); if(cret) heim_abort("SecKeyGetCSPHandle failed: %d", cret); ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeNoUI, &creds); if(ret) heim_abort("SecKeyGetCredentials failed: %d", (int)ret); ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, creds, cssmKey, &sigHandle); if(ret) heim_abort("CSSM_CSP_CreateSignatureContext failed: %d", (int)ret); in.Data = (uint8 *)from; in.Length = flen; sig.Data = (uint8 *)to; sig.Length = kc->keysize; cret = CSSM_SignData(sigHandle, &in, 1, stype, &sig); if(cret) { /* cssmErrorString(cret); */ fret = -1; } else { fret = 1; *tlen = (unsigned int)sig.Length; } if(sigHandle) CSSM_DeleteContext(sigHandle); return fret; }
/* sign with RSA blinging option */ static CSSM_RETURN _cspSign(CSSM_CSP_HANDLE cspHand, uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. CSSM_KEY_PTR key, // private key const CSSM_DATA *text, CSSM_BOOL rsaBlinding, CSSM_DATA_PTR sig) // RETURNED { CSSM_CC_HANDLE sigHand; CSSM_RETURN crtn; CSSM_RETURN ocrtn = CSSM_OK; const CSSM_DATA *ptext; CSSM_DATA digest = {0, NULL}; CSSM_ALGORITHMS digestAlg = CSSM_ALGID_NONE; /* handle special cases for raw sign */ switch(algorithm) { case CSSM_ALGID_SHA1: digestAlg = CSSM_ALGID_SHA1; algorithm = CSSM_ALGID_RSA; break; case CSSM_ALGID_MD5: digestAlg = CSSM_ALGID_MD5; algorithm = CSSM_ALGID_RSA; break; case CSSM_ALGID_DSA: digestAlg = CSSM_ALGID_SHA1; algorithm = CSSM_ALGID_DSA; break; default: break; } if(digestAlg != CSSM_ALGID_NONE) { crtn = cspDigest(cspHand, digestAlg, CSSM_FALSE, // mallocDigest text, &digest); if(crtn) { return crtn; } /* sign digest with raw RSA/DSA */ ptext = &digest; } else { ptext = text; } crtn = CSSM_CSP_CreateSignatureContext(cspHand, algorithm, NULL, // passPhrase key, &sigHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext (1)", crtn); return crtn; } if(rsaBlinding) { CSSM_CONTEXT_ATTRIBUTE newAttr; newAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; newAttr.AttributeLength = sizeof(uint32); newAttr.Attribute.Uint32 = 1; crtn = CSSM_UpdateContextAttributes(sigHand, 1, &newAttr); if(crtn) { printError("CSSM_UpdateContextAttributes", crtn); return crtn; } } crtn = CSSM_SignData(sigHand, ptext, 1, digestAlg, sig); if(crtn) { printError("CSSM_SignData", crtn); ocrtn = crtn; } crtn = CSSM_DeleteContext(sigHand); if(crtn) { printError("CSSM_DeleteContext", crtn); ocrtn = crtn; } if(digest.Data != NULL) { CSSM_FREE(digest.Data); } return ocrtn; }
int main(int argc, char **argv) { int arg; char *argp; unsigned oloop; unsigned iloop; CSSM_DATA ptext = {0, NULL}; CSSM_CSP_HANDLE cspHand; int i; int rtn = 0; uint32 keySizeInBits = 0; CSSM_KEY pubKey; CSSM_KEY privKey; CSSM_DATA sig = {0, NULL}; CSSM_DATA digest = {0, NULL}; CSSM_RETURN crtn; const char *digestStr; /* * User-spec'd params */ CSSM_BOOL keySizeSpec = CSSM_FALSE; unsigned oloops = OLOOPS_DEF; unsigned iloops = ILOOPS_DEF; CSSM_BOOL verbose = CSSM_FALSE; CSSM_BOOL quiet = CSSM_FALSE; unsigned pauseInterval = 0; CSSM_BOOL bareCsp = CSSM_TRUE; CSSM_ALGORITHMS rawSigAlg = CSSM_ALGID_RSA; for(arg=1; arg<argc; arg++) { argp = argv[arg]; switch(argp[0]) { case 'a': switch(argp[2]) { case 'r': rawSigAlg = CSSM_ALGID_RSA; break; case 'd': rawSigAlg = CSSM_ALGID_DSA; break; default: usage(argv); } break; case 'l': oloops = atoi(&argp[2]); break; case 'i': iloops = atoi(&argp[2]); break; case 'k': keySizeInBits = atoi(&argp[2]); keySizeSpec = CSSM_TRUE; break; case 'v': verbose = CSSM_TRUE; break; case 'D': bareCsp = CSSM_FALSE; break; case 'q': quiet = CSSM_TRUE; break; case 'p': pauseInterval = atoi(&argp[2]);; break; case 'h': default: usage(argv); } } ptext.Data = (uint8 *)CSSM_MALLOC(MAX_TEXT_SIZE); if(ptext.Data == NULL) { printf("Insufficient heap space\n"); exit(1); } /* ptext length set in inner test loop */ printf("Starting rawRsaSig; args: "); for(i=1; i<argc; i++) { printf("%s ", argv[i]); } printf("\n"); cspHand = cspDlDbStartup(bareCsp, NULL); if(cspHand == 0) { exit(1); } if(pauseInterval) { fpurge(stdin); printf("Top of test; hit CR to proceed: "); getchar(); } for(oloop=0; ; oloop++) { /* key size? */ if(!keySizeSpec) { /* random key size */ keySizeInBits = randKeySizeBits(rawSigAlg, OT_Sign); } if(!quiet) { if(verbose || ((oloop % LOOP_NOTIFY) == 0)) { printf("...oloop %d keySize %u\n", oloop, (unsigned)keySizeInBits); } } /* generate a key pair */ crtn = cspGenKeyPair(cspHand, rawSigAlg, "foo", 3, keySizeInBits, &pubKey, CSSM_TRUE, // all keys ref for speed CSSM_KEYUSE_VERIFY, CSSM_KEYBLOB_RAW_FORMAT_NONE, &privKey, CSSM_TRUE, CSSM_KEYUSE_SIGN, CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_FALSE); // genSeed not used if(crtn) { return testError(quiet); } for(iloop=0; iloop<iloops; iloop++) { CSSM_ALGORITHMS sigAlg; CSSM_ALGORITHMS digestAlg; CSSM_CC_HANDLE sigHand; /* alternate digest algs for RSA */ if(rawSigAlg == CSSM_ALGID_RSA) { if(iloop & 1) { sigAlg = CSSM_ALGID_SHA1WithRSA; digestAlg = CSSM_ALGID_SHA1; digestStr = "SHA1"; } else { sigAlg = CSSM_ALGID_MD5WithRSA; digestAlg = CSSM_ALGID_MD5; digestStr = "MD5 "; } } else { sigAlg = CSSM_ALGID_SHA1WithDSA; digestAlg = CSSM_ALGID_SHA1; digestStr = "SHA1"; } /* new plaintext each inner loop */ simpleGenData(&ptext, 1, MAX_TEXT_SIZE); if(!quiet) { if(verbose || ((iloop % LOOP_NOTIFY) == 0)) { printf(" ...iloop %d digest %s text size %lu\n", iloop, digestStr, ptext.Length); } } /*** phase 1 ***/ /* digest+sign */ crtn = cspStagedSign(cspHand, sigAlg, &privKey, &ptext, DO_MULTI_UPDATE, // multiUpdates &sig); if(crtn && testError(quiet)) { goto abort; } /* digest */ crtn = cspStagedDigest(cspHand, digestAlg, CSSM_FALSE, // mallocDigest DO_MULTI_UPDATE, // multiUpdates &ptext, &digest); if(crtn && testError(quiet)) { goto abort; } /* raw RSA/DSA verify */ crtn = CSSM_CSP_CreateSignatureContext(cspHand, rawSigAlg, NULL, // passPhrase &pubKey, &sigHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext (1)", crtn); return crtn; } crtn = CSSM_VerifyData(sigHand, &digest, 1, digestAlg, &sig); if(crtn) { printError("CSSM_VerifyData(raw RSA)", crtn); if(testError(quiet)) { goto abort; } } /* free resources - reuse the digest for raw sign */ appFreeCssmData(&sig, CSSM_FALSE); CSSM_DeleteContext(sigHand); /*** phase 2 ***/ /* raw RSA/DSA sign */ crtn = CSSM_CSP_CreateSignatureContext(cspHand, rawSigAlg, NULL, // passPhrase &privKey, &sigHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext (1)", crtn); return crtn; } crtn = CSSM_SignData(sigHand, &digest, 1, digestAlg, &sig); if(crtn) { printError("CSSM_SignData(raw RSA)", crtn); if(testError(quiet)) { goto abort; } } /* all-in-one verify */ crtn = cspStagedSigVerify(cspHand, sigAlg, &pubKey, &ptext, &sig, DO_MULTI_UPDATE, // multiUpdates CSSM_OK); if(crtn && testError(quiet)) { goto abort; } /* clean up */ appFreeCssmData(&sig, CSSM_FALSE); appFreeCssmData(&digest, CSSM_FALSE); CSSM_DeleteContext(sigHand); } /* end of inner loop */ /* free keys */ cspFreeKey(cspHand, &pubKey); cspFreeKey(cspHand, &privKey); if(oloops && (oloop == oloops)) { break; } if(pauseInterval && ((oloop % pauseInterval) == 0)) { fpurge(stdin); printf("hit CR to proceed: "); getchar(); } } abort: cspShutdown(cspHand, bareCsp); if(pauseInterval) { fpurge(stdin); printf("ModuleDetach/Unload complete; hit CR to exit: "); getchar(); } if((rtn == 0) && !quiet) { printf("%s test complete\n", argv[0]); } CSSM_FREE(ptext.Data); return rtn; }