X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/libsecurity_apple_csp/lib/opensshWrap.cpp diff --git a/libsecurity_apple_csp/lib/opensshWrap.cpp b/libsecurity_apple_csp/lib/opensshWrap.cpp deleted file mode 100644 index 18f448ee..00000000 --- a/libsecurity_apple_csp/lib/opensshWrap.cpp +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * opensshCoding.h - Encoding and decoding of OpenSSH format public keys. - * - * Created 8/29/2006 by dmitch. - */ - -#include "AppleCSPSession.h" -#include "AppleCSPContext.h" -#include "AppleCSPUtils.h" -#include "AppleCSPKeys.h" -#include "RSA_DSA_Keys.h" -#include "opensshCoding.h" -#include "cspdebugging.h" -#include -#include -#include -#include -#include - -static const char *authfile_id_string = "SSH PRIVATE KEY FILE FORMAT 1.1\n"; - -/* default comment on encode if app doesn't provide DescriptiveData */ -#define OPENSSH1_COMMENT "Encoded by Mac OS X Security.framework" - -/* from openssh cipher.h */ -#define SSH_CIPHER_NONE 0 /* no encryption */ -#define SSH_CIPHER_IDEA 1 /* IDEA CFB */ -#define SSH_CIPHER_DES 2 /* DES CBC */ -#define SSH_CIPHER_3DES 3 /* 3DES CBC */ -#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */ -#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */ -#define SSH_CIPHER_BLOWFISH 6 -#define SSH_CIPHER_RESERVED 7 - -#pragma mark --- utilities --- - -static void appendUint16( - CFMutableDataRef cfOut, - uint16_t ui) -{ - UInt8 buf[sizeof(uint16_t)]; - - buf[1] = ui & 0xff; - ui >>= 8; - buf[0] = ui; - CFDataAppendBytes(cfOut, buf, sizeof(uint16_t)); -} - -static uint16_t readUint16( - const unsigned char *&cp, // IN/OUT - unsigned &len) // IN/OUT -{ - uint16_t r = *cp++; - r <<= 8; - r |= *cp++; - len -= 2; - return r; -} - -/* Write BIGNUM, OpenSSH-1 version */ -static CSSM_RETURN appendBigNum( - CFMutableDataRef cfOut, - const BIGNUM *bn) -{ - /* 16 bits of numbits */ - unsigned numBits = BN_num_bits(bn); - appendUint16(cfOut, numBits); - - /* serialize the bytes */ - int numBytes = (numBits + 7) / 8; - unsigned char outBytes[numBytes]; // gcc is so cool... - int moved = BN_bn2bin(bn, outBytes); - if(moved != numBytes) { - errorLog0("appendBigNum: BN_bn2bin() screwup\n"); - return CSSMERR_CSP_INTERNAL_ERROR; - } - CFDataAppendBytes(cfOut, (UInt8 *)outBytes, numBytes); - return CSSM_OK; -} - -/* Read BIGNUM, OpenSSH-1 version */ -static BIGNUM *readBigNum( - const unsigned char *&cp, // IN/OUT - unsigned &remLen) // IN/OUT -{ - if(remLen < sizeof(uint16_t)) { - errorLog0("readBigNum: short record(1)\n"); - return NULL; - } - uint16_t numBits = readUint16(cp, remLen); - unsigned bytes = (numBits + 7) / 8; - if(remLen < bytes) { - errorLog0("readBigNum: short record(2)\n"); - return NULL; - } - BIGNUM *bn = BN_bin2bn(cp, bytes, NULL); - if(bn == NULL) { - errorLog0("readBigNum: BN_bin2bn error\n"); - return NULL; - } - cp += bytes; - remLen -= bytes; - return bn; -} - -/* - * Calculate d mod{p-1,q-1} - * Used when decoding OpenSSH-1 private RSA key. - */ -static CSSM_RETURN rsa_generate_additional_parameters(RSA *rsa) -{ - BIGNUM *aux; - BN_CTX *ctx; - - if((rsa->dmq1 = BN_new()) == NULL) { - errorLog0("rsa_generate_additional_parameters: BN_new failed"); - return CSSMERR_CSP_INTERNAL_ERROR; - } - if((rsa->dmp1 = BN_new()) == NULL) { - errorLog0("rsa_generate_additional_parameters: BN_new failed"); - return CSSMERR_CSP_INTERNAL_ERROR; - } - if ((aux = BN_new()) == NULL) { - errorLog0("rsa_generate_additional_parameters: BN_new failed"); - return CSSMERR_CSP_INTERNAL_ERROR; - } - if ((ctx = BN_CTX_new()) == NULL) { - errorLog0("rsa_generate_additional_parameters: BN_CTX_new failed"); - BN_clear_free(aux); - return CSSMERR_CSP_INTERNAL_ERROR; - } - - BN_sub(aux, rsa->q, BN_value_one()); - BN_mod(rsa->dmq1, rsa->d, aux, ctx); - - BN_sub(aux, rsa->p, BN_value_one()); - BN_mod(rsa->dmp1, rsa->d, aux, ctx); - - BN_clear_free(aux); - BN_CTX_free(ctx); - return CSSM_OK; -} - -#pragma mark --- encrypt/decrypt --- - -/* - * Encrypt/decrypt the secret portion of an OpenSSHv1 format RSA private key. - */ -static CSSM_RETURN ssh1DES3Crypt( - unsigned char cipher, - bool doEncrypt, - const unsigned char *inText, - unsigned inTextLen, - const uint8 *key, // MD5(password) - CSSM_SIZE keyLen, - unsigned char *outText, // data RETURNED here, caller mallocs. - unsigned *outTextLen) // RETURNED -{ - switch(cipher) { - case SSH_CIPHER_3DES: - break; - case SSH_CIPHER_NONE: - /* cleartext RSA private key, e.g. host key. */ - memmove(outText, inText, inTextLen); - *outTextLen = inTextLen; - return CSSM_OK; - default: - /* who knows how we're going to figure these out */ - errorLog1("***ssh1DES3Crypt: Unsupported cipher (%u)\n", cipher); - return CSSMERR_CSP_INVALID_KEY; - } - - if(keyLen != CC_MD5_DIGEST_LENGTH) { - errorLog0("ssh1DES3Crypt: bad key length\n"); - return CSSMERR_CSP_INVALID_KEY; - } - - /* three keys from that, like so: */ - unsigned char k1[kCCKeySizeDES]; - unsigned char k2[kCCKeySizeDES]; - unsigned char k3[kCCKeySizeDES]; - memmove(k1, key, kCCKeySizeDES); - memmove(k2, key + kCCKeySizeDES, kCCKeySizeDES); - memmove(k3, key, kCCKeySizeDES); - - CCOperation op1_3; - CCOperation op2; - if(doEncrypt) { - op1_3 = kCCEncrypt; - op2 = kCCDecrypt; - } - else { - op1_3 = kCCDecrypt; - op2 = kCCEncrypt; - } - - /* the openssh v1 pseudo triple DES. Each DES pass has its own CBC. */ - size_t moved = 0; - - CCCryptorStatus cstat = CCCrypt(op1_3, kCCAlgorithmDES, - 0, // no padding - k1, kCCKeySizeDES, - NULL, // IV - inText, inTextLen, - outText, inTextLen, &moved); - if(cstat) { - /* should never happen */ - errorLog1("***ssh1DES3Crypt: CCCrypt()(1) returned %u\n", (unsigned)cstat); - return CSSMERR_CSP_INTERNAL_ERROR; - } - cstat = CCCrypt(op2, kCCAlgorithmDES, - 0, // no padding - SSH does that itself - k2, kCCKeySizeDES, - NULL, // IV - outText, moved, - outText, inTextLen, &moved); - if(cstat) { - errorLog1("***ssh1DES3Crypt: CCCrypt()(2) returned %u\n", (unsigned)cstat); - return CSSMERR_CSP_INTERNAL_ERROR; - } - cstat = CCCrypt(op1_3, kCCAlgorithmDES, - 0, // no padding - SSH does that itself - k3, kCCKeySizeDES, - NULL, // IV - outText, moved, - outText, inTextLen, &moved); - if(cstat) { - errorLog1("***ssh1DES3Crypt: CCCrypt()(3) returned %u\n", (unsigned)cstat); - return CSSMERR_CSP_INTERNAL_ERROR; - } - - *outTextLen = (unsigned)moved; - return CSSM_OK; -} - -#pragma mark --- DeriveKey --- - -/* - * Key derivation for OpenSSH1 private key wrap/unwrap. - * This is pretty trivial, it's just an MD5() operation. The main - * purpose for doing this in a DeriveKey operation is to enable the - * use of either Secure Passphrases, obtained by securityd/SecurityAgent, - * or app-specified data. - */ -void AppleCSPSession::DeriveKey_OpenSSH1( - const Context &context, - CSSM_ALGORITHMS algId, - const CssmData &Param, // IV optional, mallocd by app to indicate - // size - CSSM_DATA *keyData) // mallocd by caller to indicate size - must be - // size of MD5 digest! -{ - CSSM_DATA pwd = {0, NULL}; - - if(keyData->Length != CC_MD5_DIGEST_LENGTH) { - errorLog0("DeriveKey_OpenSSH1: invalid key length\n"); - CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); - } - - /* password from either Seed.Param or from base key */ - CssmCryptoData *cryptData = - context.get(CSSM_ATTRIBUTE_SEED); - if((cryptData != NULL) && (cryptData->Param.Length != 0)) { - pwd = cryptData->Param; - } - else { - /* Get secure passphrase from base key */ - CssmKey *passKey = context.get(CSSM_ATTRIBUTE_KEY); - if (passKey != NULL) { - AppleCSPContext::symmetricKeyBits(context, *this, - CSSM_ALGID_SECURE_PASSPHRASE, CSSM_KEYUSE_DERIVE, - pwd.Data, pwd.Length); - } - } - - if(pwd.Data == NULL) { - errorLog0("DeriveKey_PKCS5_V1_5: null Passphrase\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_DATA); - } - if(pwd.Length == 0) { - errorLog0("DeriveKey_PKCS5_V1_5: zero length passphrase\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_INPUT_POINTER); - } - - /* here it is */ - CC_MD5(pwd.Data, (CC_LONG)pwd.Length, keyData->Data); - -} - -#pragma mark --- Encode/Wrap OpenSSHv1 private key --- - -/* - * Encode OpenSSHv1 private key, with or without encryption. - * This used for generating key blobs of format CSSM_KEYBLOB_RAW_FORMAT_OPENSSH - * as well as wrapping keys in format CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1. - */ -CSSM_RETURN encodeOpenSSHv1PrivKey( - RSA *rsa, - const uint8 *comment, /* optional */ - unsigned commentLen, - const uint8 *encryptKey, /* optional; if present, it's 16 bytes of MD5(password) */ - CFDataRef *encodedKey) /* RETURNED */ -{ - CFMutableDataRef cfOut = CFDataCreateMutable(NULL, 0); - CSSM_RETURN ourRtn = CSSM_OK; - - /* ID string including NULL */ - CFDataAppendBytes(cfOut, (const UInt8 *)authfile_id_string, strlen(authfile_id_string) + 1); - - /* one byte cipher */ - UInt8 cipherSpec = encryptKey ? SSH_CIPHER_3DES : SSH_CIPHER_NONE; - CFDataAppendBytes(cfOut, &cipherSpec, 1); - - /* spares */ - UInt8 spares[4] = {0}; - CFDataAppendBytes(cfOut, spares, 4); - - /* - * Clear text public key: - * uint32 bits - * bignum n - * bignum e - */ - uint32_t keybits = RSA_size(rsa) * 8; - appendUint32(cfOut, keybits); - appendBigNum(cfOut, rsa->n); - appendBigNum(cfOut, rsa->e); - - /* - * Comment string. - * The format appears to require this, or else we wouldn't know - * when we've got to the ciphertext on decode. - */ - if((comment == NULL) || (commentLen == 0)) { - comment = (const UInt8 *)OPENSSH1_COMMENT; - commentLen = strlen(OPENSSH1_COMMENT); - } - appendUint32(cfOut, commentLen); - CFDataAppendBytes(cfOut, comment, commentLen); - - /* - * Remainder is encrypted, consisting of - * - * [0-1] -- random bytes - * [2-3] -- copy of [01] for passphrase validity checking - * buffer_put_bignum(d) - * buffer_put_bignum(iqmp) - * buffer_put_bignum(q) - * buffer_put_bignum(p) - * pad to block size - */ - CFMutableDataRef ptext = CFDataCreateMutable(NULL, 0); - - /* [0..3] check bytes */ - UInt8 checkBytes[4]; - DevRandomGenerator rng = DevRandomGenerator(); - rng.random(checkBytes, 2); - checkBytes[2] = checkBytes[0]; - checkBytes[3] = checkBytes[1]; - CFDataAppendBytes(ptext, checkBytes, 4); - - /* d, iqmp, q, p */ - appendBigNum(ptext, rsa->d); - appendBigNum(ptext, rsa->iqmp); - appendBigNum(ptext, rsa->q); - appendBigNum(ptext, rsa->p); - - /* pad to block boundary */ - CFIndex ptextLen = CFDataGetLength(ptext); - unsigned padding = 0; - unsigned rem = (unsigned)ptextLen & 0x7; - if(rem) { - padding = 8 - rem; - } - UInt8 padByte = 0; - for(unsigned dex=0; dex(unwrappedBinKey); - RSA *rsa = rPubBinKey.mRsaKey; - CASSERT(rsa != NULL); - - /* - * Get the raw password bits from the wrapping key. - * Our caller verified that the context has a symmetric key; this call - * ensures that the key is of algorithm CSSM_ALGID_OPENSSH1. - * Key length 0 means no encryption. - */ - CSSM_SIZE wrappingKeyLen = 0; - uint8 *wrappingKey = NULL; - - AppleCSPContext::symmetricKeyBits(context, *this, - CSSM_ALGID_OPENSSH1, CSSM_KEYUSE_WRAP, - wrappingKey, wrappingKeyLen); - if(wrappingKeyLen != CC_MD5_DIGEST_LENGTH) { - errorLog0("AppleCSPSession::WrapKeyOpenSSH1: bad wrapping key length\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - - CFDataRef cfOut = NULL; - - /* - * Optional comment string from DescriptiveData. - */ - const UInt8 *comment = NULL; - unsigned commentLen = 0; - if((DescriptiveData != NULL) && (DescriptiveData->Length != 0)) { - comment = (const UInt8 *)DescriptiveData->Data; - commentLen = (unsigned)DescriptiveData->Length; - } - - /* generate the encrypted blob */ - CSSM_RETURN crtn = encodeOpenSSHv1PrivKey(rsa, comment, commentLen, wrappingKey, &cfOut); - if(crtn) { - CssmError::throwMe(crtn); - } - - /* allocate key data in session's memory space */ - CFIndex len = CFDataGetLength(cfOut); - setUpData(WrappedKey.KeyData, len, normAllocator); - memmove(WrappedKey.KeyData.Data, CFDataGetBytePtr(cfOut), len); - CFRelease(cfOut); - - /* outgoing header */ - WrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; - // OK to be zero or not present - WrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_NONE; - WrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1; -} - -#pragma mark --- Decode/Unwrap OpenSSHv1 private key --- - -/* - * Decode OpenSSHv1 private, optionally decrypting the secret portion. - * This used for decoding key blobs of format CSSM_KEYBLOB_RAW_FORMAT_OPENSSH - * as well as unwrapping keys in format CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1. - */ -CSSM_RETURN decodeOpenSSHv1PrivKey( - const unsigned char *encodedKey, - unsigned encodedKeyLen, - RSA *rsa, - const uint8 *decryptKey, /* optional; if present, it's 16 bytes of MD5(password) */ - uint8 **comment, /* optional, mallocd and RETURNED */ - unsigned *commentLen) /* RETURNED */ -{ - unsigned len = (unsigned)strlen(authfile_id_string); - const unsigned char *cp = encodedKey; - unsigned remLen = encodedKeyLen; - CSSM_RETURN ourRtn = CSSM_OK; - - /* length: ID string, NULL, Cipher, 4-byte spare */ - if(remLen < (len + 6)) { - errorLog0("decodeOpenSSHv1PrivKey: short record(1)\n"); - return CSSMERR_CSP_INVALID_KEY; - } - - /* ID string plus a NULL */ - if(memcmp(authfile_id_string, cp, len)) { - errorLog0("decodeOpenSSHv1PrivKey: bad header\n"); - return CSSMERR_CSP_INVALID_KEY; - } - cp += (len + 1); - remLen -= (len + 1); - - /* cipher */ - unsigned char cipherSpec = *cp; - switch(cipherSpec) { - case SSH_CIPHER_NONE: - if(decryptKey != NULL) { - errorLog0("decodeOpenSSHv1PrivKey: Attempt to decrypt plaintext key\n"); - return CSSMERR_CSP_INVALID_KEY; - } - break; - case SSH_CIPHER_3DES: - if(decryptKey == NULL) { - errorLog0("decodeOpenSSHv1PrivKey: Encrypted key with no decryptKey\n"); - return CSSMERR_CSP_INVALID_KEY; - } - break; - default: - /* I hope we don't see any other values here */ - errorLog1("decodeOpenSSHv1PrivKey: unknown cipherSpec (%u)\n", cipherSpec); - return CSSMERR_CSP_INVALID_KEY; - } - - /* skip cipher, spares */ - cp += 5; - remLen -= 5; - - /* - * Clear text public key: - * uint32 bits - * bignum n - * bignum e - */ - if(remLen < sizeof(uint32_t)) { - errorLog0("decodeOpenSSHv1PrivKey: bad len(1)\n"); - return CSSMERR_CSP_INVALID_KEY; - } - /* skip over bits */ - readUint32(cp, remLen); - rsa->n = readBigNum(cp, remLen); - if(rsa->n == NULL) { - errorLog0("decodeOpenSSHv1PrivKey: error decoding n\n"); - return CSSMERR_CSP_INVALID_KEY; - } - rsa->e = readBigNum(cp, remLen); - if(rsa->e == NULL) { - errorLog0("decodeOpenSSHv1PrivKey: error decoding e\n"); - return CSSMERR_CSP_INVALID_KEY; - } - - /* comment string: 4-byte length and the string w/o NULL */ - if(remLen < sizeof(uint32_t)) { - errorLog0("decodeOpenSSHv1PrivKey: bad len(2)\n"); - return CSSMERR_CSP_INVALID_KEY; - } - uint32_t commLen = readUint32(cp, remLen); - if(commLen > remLen) { - errorLog0("decodeOpenSSHv1PrivKey: bad len(3)\n"); - return CSSMERR_CSP_INVALID_KEY; - } - if(comment) { - *comment = (uint8 *)malloc(commLen); - *commentLen = commLen; - memcpy(*comment, cp, commLen); - } - - cp += commLen; - remLen -= commLen; - - /* everything that remains is ciphertext */ - unsigned char *ptext = (unsigned char *)malloc(remLen); - unsigned ptextLen = 0; - ourRtn = ssh1DES3Crypt(cipherSpec, false, cp, remLen, - decryptKey, decryptKey ? CC_MD5_DIGEST_LENGTH : 0, - ptext, &ptextLen); - if(ourRtn) { - errorLog0("UnwrapKeyOpenSSH1: decrypt error\n"); - ourRtn = CSSMERR_CSP_INVALID_KEY; - goto errOut; - } - - /* plaintext contents: - - [0-1] -- random bytes - [2-3] -- copy of [01] for passphrase validity checking - buffer_put_bignum(d) - buffer_put_bignum(iqmp) - buffer_put_bignum(q) - buffer_put_bignum(p) - pad to block size - */ - cp = ptext; - remLen = ptextLen; - if(remLen < 4) { - errorLog0("UnwrapKeyOpenSSH1: bad len(4)\n"); - ourRtn = CSSMERR_CSP_INVALID_KEY; - goto errOut; - } - if((cp[0] != cp[2]) || (cp[1] != cp[3])) { - /* decrypt fail */ - errorLog0("UnwrapKeyOpenSSH1: check byte error\n"); - ourRtn = CSSMERR_CSP_INVALID_KEY; - goto errOut; - } - cp += 4; - remLen -= 4; - - /* remainder comprises private portion of RSA key */ - rsa->d = readBigNum(cp, remLen); - if(rsa->d == NULL) { - errorLog0("UnwrapKeyOpenSSH1: error decoding d\n"); - ourRtn = CSSMERR_CSP_INVALID_KEY; - goto errOut; - } - rsa->iqmp = readBigNum(cp, remLen); - if(rsa->iqmp == NULL) { - errorLog0("UnwrapKeyOpenSSH1: error decoding iqmp\n"); - ourRtn = CSSMERR_CSP_INVALID_KEY; - goto errOut; - } - rsa->q = readBigNum(cp, remLen); - if(rsa->q == NULL) { - errorLog0("UnwrapKeyOpenSSH1: error decoding q\n"); - ourRtn = CSSMERR_CSP_INVALID_KEY; - goto errOut; - } - rsa->p = readBigNum(cp, remLen); - if(rsa->p == NULL) { - errorLog0("UnwrapKeyOpenSSH1: error decoding p\n"); - ourRtn = CSSMERR_CSP_INVALID_KEY; - goto errOut; - } - - /* calculate d mod{p-1,q-1} */ - ourRtn = rsa_generate_additional_parameters(rsa); - -errOut: - if(ptext) { - memset(ptext, 0, ptextLen); - free(ptext); - } - return ourRtn; -} - -void AppleCSPSession::UnwrapKeyOpenSSH1( - CSSM_CC_HANDLE CCHandle, - const Context &context, - const CssmKey &WrappedKey, - const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, - CssmKey &UnwrappedKey, - CssmData &DescriptiveData, - CSSM_PRIVILEGE Privilege, - cspKeyStorage keyStorage) -{ - /* - * Get the raw password bits from the unwrapping key. - * Our caller verified that the context has a symmetric key; this call - * ensures that the key is of algorithm CSSM_ALGID_OPENSSH1. - */ - CSSM_SIZE unwrapKeyLen = 0; - uint8 *unwrapKey = NULL; - - AppleCSPContext::symmetricKeyBits(context, *this, - CSSM_ALGID_OPENSSH1, CSSM_KEYUSE_UNWRAP, - unwrapKey, unwrapKeyLen); - if((unwrapKey == NULL) || (unwrapKeyLen != CC_MD5_DIGEST_LENGTH)) { - errorLog0("AppleCSPSession::UnwrapKeyOpenSSH1: bad unwrapping key length\n"); - CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); - } - - RSA *rsa = RSA_new(); - CSSM_RETURN ourRtn = CSSM_OK; - unsigned char *comment = NULL; - unsigned commentLen = 0; - RSABinaryKey *binKey = NULL; - - ourRtn = decodeOpenSSHv1PrivKey((const unsigned char *)WrappedKey.KeyData.Data, - (unsigned)WrappedKey.KeyData.Length, - rsa, unwrapKey, &comment, &commentLen); - if(ourRtn) { - goto errOut; - } - if(comment) { - setUpCssmData(DescriptiveData, commentLen, normAllocator); - memcpy(DescriptiveData.Data, comment, commentLen); - } - - /* - * Our caller ensured that we're only generating a reference key, - * which we do like so: - */ - binKey = new RSABinaryKey(rsa); - addRefKey(*binKey, UnwrappedKey); - -errOut: - if(ourRtn) { - if(rsa) { - RSA_free(rsa); - } - CssmError::throwMe(ourRtn); - } -}