#if USE_CDSA_CRYPTO
#include "ssl.h"
#include "sslMemory.h"
#include "sslDebug.h"
#include "sslBER.h"
#include "sslCrypto.h"
#include <string.h>
#include "appleCdsa.h"
#include "SecureTransportPriv.h"
#include <string.h>
#include <Security/SecAsn1Coder.h>
#include <Security/keyTemplates.h>
#include <security_asn1/nssUtils.h>
#include <Security/oidsattr.h>
#include <Security/oidsalg.h>
#include <security_asn1/secasn1.h>
#define SSLBUF_TO_SECITEM(sb, cd) { \
(cd)->Length = (sb)->length; \
(cd)->Data = (sb)->data; \
}
#define CHUNKSIZE_DEF 1024
OSStatus sslDecodeRsaBlob(
const SSLBuffer *blob,
SSLBuffer *modulus,
SSLBuffer *exponent)
{
SECStatus rv;
OSStatus srtn;
NSS_RSAPublicKeyPKCS1 nssPubKey = {};
PLArenaPool *pool;
assert(blob != NULL);
assert(modulus != NULL);
assert(exponent != NULL);
pool = PORT_NewArena(CHUNKSIZE_DEF);
rv = SEC_ASN1Decode(pool, &nssPubKey,
kSecAsn1RSAPublicKeyPKCS1Template, (const char *)blob->data, blob->length);
if (rv != SECSuccess)
srtn = errSSLBadCert;
else {
srtn = SSLCopyBufferFromData(nssPubKey.modulus.Data,
nssPubKey.modulus.Length, modulus);
if(!srtn) {
srtn = SSLCopyBufferFromData(nssPubKey.publicExponent.Data,
nssPubKey.publicExponent.Length, exponent);
}
}
PORT_FreeArena(pool, PR_TRUE);
return srtn;
}
OSStatus sslEncodeRsaBlob(
const SSLBuffer *modulus,
const SSLBuffer *exponent,
SSLBuffer *blob)
{
PLArenaPool *pool;
OSStatus srtn;
SECItem *encBlob, dest = {};
NSS_RSAPublicKeyPKCS1 nssPubKey;
assert((modulus != NULL) && (exponent != NULL));
SSLBUF_TO_SECITEM(modulus, &nssPubKey.modulus);
SSLBUF_TO_SECITEM(exponent, &nssPubKey.publicExponent);
pool = PORT_NewArena(CHUNKSIZE_DEF);
encBlob = SEC_ASN1EncodeItem(pool, &dest, &nssPubKey,
kSecAsn1RSAPublicKeyPKCS1Template);
if (!encBlob)
srtn = memFullErr;
else {
srtn = SSLCopyBufferFromData(encBlob->Data, encBlob->Length, blob);
}
PORT_FreeArena(pool, PR_TRUE);
return srtn;
}
#if APPLE_DH
OSStatus sslDecodeDhParams(
const SSLBuffer *blob,
SSLBuffer *prime,
SSLBuffer *generator)
{
SECStatus rv;
OSStatus srtn;
NSS_DHParameterBlock paramBlock = {};
PLArenaPool *pool;
assert(blob != NULL);
assert(prime != NULL);
assert(generator != NULL);
pool = PORT_NewArena(CHUNKSIZE_DEF);
rv = SEC_ASN1Decode(pool, ¶mBlock.params,
kSecAsn1DHParameterTemplate, (const char *)blob->data, blob->length);
if (rv != SECSuccess) {
memset(¶mBlock, 0, sizeof(paramBlock));
rv = SEC_ASN1Decode(pool, ¶mBlock,
kSecAsn1DHParameterBlockTemplate,
(const char *)blob->data, blob->length);
}
if (rv != SECSuccess) {
sslErrorLog("sslDecodeDhParams: both CDSA and openssl format"
"failed\n");
srtn = errSSLCrypto;
}
else {
srtn = SSLCopyBufferFromData(paramBlock.params.prime.Data,
paramBlock.params.prime.Length, prime);
if(!srtn) {
srtn = SSLCopyBufferFromData(paramBlock.params.base.Data,
paramBlock.params.base.Length, generator);
}
}
PORT_FreeArena(pool, PR_TRUE);
return srtn;
}
OSStatus sslEncodeDhParams(
const SSLBuffer *prime,
const SSLBuffer *generator,
SSLBuffer *blob)
{
PLArenaPool *pool;
OSStatus srtn;
SECItem *encBlob, dest = {};
NSS_DHParameter dhParams;
assert((prime != NULL) && (generator != NULL));
SSLBUF_TO_SECITEM(prime, &dhParams.prime);
SSLBUF_TO_SECITEM(generator, &dhParams.base);
dhParams.privateValueLength.Data = NULL;
dhParams.privateValueLength.Length = 0;
pool = PORT_NewArena(CHUNKSIZE_DEF);
encBlob = SEC_ASN1EncodeItem(pool, &dest, &dhParams,
kSecAsn1DHParameterTemplate);
if (!encBlob)
srtn = memFullErr;
else {
srtn = SSLCopyBufferFromData(encBlob->Data, encBlob->Length, blob);
}
PORT_FreeArena(pool, PR_TRUE);
return srtn;
}
#endif
OSStatus sslEcdsaPeerCurve(
CSSM_KEY_PTR pubKey,
SSL_ECDSA_NamedCurve *namedCurve)
{
SecAsn1CoderRef coder = NULL;
CSSM_X509_SUBJECT_PUBLIC_KEY_INFO subjPubKeyInfo;
CSSM_X509_ALGORITHM_IDENTIFIER *algId = &subjPubKeyInfo.algorithm;
CSSM_OID curveOid;
OSStatus ortn;
CSSM_KEYHEADER *hdr = &pubKey->KeyHeader;
if(hdr->AlgorithmId != CSSM_ALGID_ECDSA) {
sslErrorLog("sslEcdsaPeerCurve: bad peer key algorithm\n");
return errSSLProtocol;
}
if(hdr->BlobType != CSSM_KEYBLOB_RAW) {
sslErrorLog("sslEcdsaPeerCurve: bad peer key algorithm\n");
return errSSLProtocol;
}
if(hdr->Format != CSSM_KEYBLOB_RAW_FORMAT_X509) {
sslErrorLog("sslEcdsaPeerCurve: bad peer key format\n");
return errSSLProtocol;
}
ortn = SecAsn1CoderCreate(&coder);
if(ortn) {
return errSSLInternal;
}
memset(&subjPubKeyInfo, 0, sizeof(subjPubKeyInfo));
ortn = SecAsn1DecodeData(coder, &pubKey->KeyData, kSecAsn1SubjectPublicKeyInfoTemplate,
&subjPubKeyInfo);
if(ortn) {
printf("sslEcdsaPeerCurve: error decoding public key\n");
goto errOut;
}
if(!nssCompareCssmData(&algId->algorithm, &CSSMOID_ecPublicKey)) {
printf("sslEcdsaPeerCurve: unexpected algorithm ID in public key\n");
ortn = errSSLProtocol;
goto errOut;
}
if((algId->parameters.Data[0] != BER_TAG_OID) ||
(algId->parameters.Length < 2)) {
printf("sslEcdsaPeerCurve: missing algorithm parameters in public key\n");
ortn = errSSLProtocol;
goto errOut;
}
curveOid.Data = algId->parameters.Data + 2;
curveOid.Length = algId->parameters.Length - 2;
if(nssCompareCssmData(&curveOid, &CSSMOID_secp256r1)) {
*namedCurve = SSL_Curve_secp256r1;
}
else if(nssCompareCssmData(&curveOid, &CSSMOID_secp384r1)) {
*namedCurve = SSL_Curve_secp384r1;
}
else if(nssCompareCssmData(&curveOid, &CSSMOID_secp521r1)) {
*namedCurve = SSL_Curve_secp521r1;
}
else {
printf("sslEcdsaPeerCurve: missing algorithm parameters in public key\n");
ortn = errSSLProtocol;
}
errOut:
SecAsn1CoderRelease(coder);
return ortn;
}
OSStatus sslEcdsaPubKeyBits(
CSSM_KEY_PTR pubKey,
SSLBuffer *pubBits)
{
SecAsn1CoderRef coder = NULL;
CSSM_X509_SUBJECT_PUBLIC_KEY_INFO subjPubKeyInfo;
OSStatus ortn = noErr;
CSSM_KEYHEADER *hdr = &pubKey->KeyHeader;
if(hdr->AlgorithmId != CSSM_ALGID_ECDSA) {
sslErrorLog("sslEcdsaPubKeyBits: bad peer key algorithm\n");
return errSSLProtocol;
}
if(hdr->BlobType != CSSM_KEYBLOB_RAW) {
sslErrorLog("sslEcdsaPubKeyBits: bad peer key algorithm\n");
return errSSLProtocol;
}
if(hdr->Format != CSSM_KEYBLOB_RAW_FORMAT_X509) {
sslErrorLog("sslEcdsaPubKeyBits: bad peer key format\n");
return errSSLProtocol;
}
ortn = SecAsn1CoderCreate(&coder);
if(ortn) {
return errSSLInternal;
}
memset(&subjPubKeyInfo, 0, sizeof(subjPubKeyInfo));
ortn = SecAsn1DecodeData(coder, &pubKey->KeyData, kSecAsn1SubjectPublicKeyInfoTemplate,
&subjPubKeyInfo);
if(ortn) {
printf("sslEcdsaPubKeyBits: error decoding public key\n");
goto errOut;
}
ortn = SSLCopyBufferFromData(subjPubKeyInfo.subjectPublicKey.Data,
subjPubKeyInfo.subjectPublicKey.Length >> 3, pubBits);
errOut:
SecAsn1CoderRelease(coder);
return ortn;
}
#endif