Ejemplo n.º 1
2
int rsa_test()
{
    byte   tmp[1024], tmp2[2048];
    size_t bytes, bytes2;
    RsaKey key;
    RNG    rng;
    word32 idx = 0;
    int    ret;
    byte   in[] = "Everyone gets Friday off.";
    word32 inLen = (word32)strlen((char*)in);
    byte   out[64];
    byte   plain[64];
    DecodedCert cert;

    FILE*  file = fopen(clientKey, "rb"), * file2;

    if (!file)
        return -40;

    bytes = fread(tmp, 1, 1024, file);
  
    InitRsaKey(&key, 0);  
    ret = RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes);
    if (ret != 0) return -41;

    ret = InitRng(&rng);
    if (ret != 0) return -42;

    ret = RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng);  

    ret = RsaPrivateDecrypt(out, 64, plain, sizeof(plain), &key);

    if (memcmp(plain, in, inLen)) return -45;

    ret = RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng);
    memset(plain, 0, sizeof(plain));
    ret = RsaSSL_Verify(out, 64, plain, sizeof(plain), &key);

    if (memcmp(plain, in, ret)) return -46;

    file2 = fopen(clientCert, "rb");
    if (!file2)
        return -47;

    bytes2 = fread(tmp2, 1, 2048, file2);

    InitDecodedCert(&cert, (byte*)&tmp2, 0);

    ret = ParseCert(&cert, (word32)bytes2, CERT_TYPE, NO_VERIFY, 0);
    if (ret != 0) return -48;

    FreeDecodedCert(&cert);
    FreeRsaKey(&key);

    fclose(file2);
    fclose(file);

    return 0;
}
Ejemplo n.º 2
0
void bench_rsa(void)
{
    int    i;
    byte   tmp[3072];
    size_t bytes;
    word32 idx = 0;

    byte      message[] = "Everyone gets Friday off.";
    byte      enc[512];  /* for up to 4096 bit */
    byte*     output;
    const int len = (int)strlen((char*)message);
    double    start, total, each, milliEach;

    RsaKey rsaKey;
    FILE*  file = fopen("./certs/rsa2048.der", "rb");

    if (!file) {
        printf("can't find ./certs/rsa2048.der, "
               "Please run from CyaSSL home dir\n");
        return;
    }

    InitRng(&rng);
    bytes = fread(tmp, 1, sizeof(tmp), file);
    InitRsaKey(&rsaKey, 0);
    bytes = RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes);

    start = current_time();

    for (i = 0; i < times; i++)
        bytes = RsaPublicEncrypt(message,len,enc,sizeof(enc), &rsaKey, &rng);

    total = current_time() - start;
    each  = total / times;   /* per second   */
    milliEach = each * 1000; /* milliseconds */

    printf("RSA 2048 encryption took %6.2f milliseconds, avg over %d"
           " iterations\n", milliEach, times);

    start = current_time();

    for (i = 0; i < times; i++)
        RsaPrivateDecryptInline(enc, (word32)bytes, &output, &rsaKey);

    total = current_time() - start;
    each  = total / times;   /* per second   */
    milliEach = each * 1000; /* milliseconds */

    printf("RSA 2048 decryption took %6.2f milliseconds, avg over %d"
           " iterations\n", milliEach, times);

    fclose(file);
    FreeRsaKey(&rsaKey);
}
Ejemplo n.º 3
0
/* RSA Initialize */
int CRYPT_RSA_Initialize(CRYPT_RSA_CTX* rsa)
{
    if (rsa == NULL)
        return BAD_FUNC_ARG;

    rsa->holder = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA);
    if (rsa->holder == NULL)
        return -1;

    return InitRsaKey((RsaKey*)rsa->holder, NULL);
}
Ejemplo n.º 4
0
void bench_rsa()
{
    int    i;
    byte   tmp[1024];
    size_t bytes;
    word32 idx = 0;

    byte      message[] = "Everyone gets Friday off.";
    byte      cipher[128];  /* for 1024 bit */
    byte      plain[128];   /* for 1024 bit */
    const int len = (int)strlen((char*)message);
    double    start, total, each, milliEach;
    
    RsaKey key;
    FILE*  file = fopen("./rsa1024.der", "rb");

    if (!file) {
        printf("can't find ./rsa1024.der\n");
        return;
    }

    bytes = fread(tmp, 1, 1024, file);
    InitRsaKey(&key, 0);
    bytes = RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes);

    
    start = current_time();

    for (i = 0; i < times; i++)
        RsaPublicEncrypt(message, len, cipher, sizeof(cipher), &key, &rng);

    total = current_time() - start;
    each  = total / times;   /* per second   */
    milliEach = each * 1000; /* milliseconds */

    printf("RSA 1024 encryption took %6.2f milliseconds, avg over %d" 
           " iterations\n", milliEach, times);

    start = current_time();

    for (i = 0; i < times; i++)
        RsaPrivateDecrypt(cipher, 128, plain, sizeof(plain), &key);

    total = current_time() - start;
    each  = total / times;   /* per second   */
    milliEach = each * 1000; /* milliseconds */

    printf("RSA 1024 decryption took %6.2f milliseconds, avg over %d" 
           " iterations\n", milliEach, times);

    fclose(file);
    FreeRsaKey(&key);
}
Ejemplo n.º 5
0
void bench_rsaKeyGen(void)
{
    RsaKey genKey;
    double start, total, each, milliEach;
    int    i;
    const int genTimes = 5;
  
    /* 1024 bit */ 
    start = current_time(1);

    for(i = 0; i < genTimes; i++) {
        InitRsaKey(&genKey, 0); 
        MakeRsaKey(&genKey, 1024, 65537, &rng);
        FreeRsaKey(&genKey);
    }

    total = current_time(0) - start;
    each  = total / genTimes;  /* per second  */
    milliEach = each * 1000;   /* millisconds */
    printf("\n");
    printf("RSA 1024 key generation  %6.2f milliseconds, avg over %d" 
           " iterations\n", milliEach, genTimes);

    /* 2048 bit */
    start = current_time(1);

    for(i = 0; i < genTimes; i++) {
        InitRsaKey(&genKey, 0); 
        MakeRsaKey(&genKey, 2048, 65537, &rng);
        FreeRsaKey(&genKey);
    }

    total = current_time(0) - start;
    each  = total / genTimes;  /* per second  */
    milliEach = each * 1000;   /* millisconds */
    printf("RSA 2048 key generation  %6.2f milliseconds, avg over %d" 
           " iterations\n", milliEach, genTimes);
}
Ejemplo n.º 6
0
/* check mcapi rsa */
static int check_rsa(void)
{
    CRYPT_RSA_CTX mcRsa;
    RsaKey        defRsa;
    int           ret;
    int           ret2;
    unsigned int  keySz = (unsigned int)sizeof(client_key_der_1024);
    unsigned int  idx   = 0;
    byte          out1[256];
    byte          out2[256];

    InitRsaKey(&defRsa, NULL);
    ret = CRYPT_RSA_Initialize(&mcRsa);
    if (ret != 0) {
        printf("mcapi rsa init failed\n");
        return -1;
    }

    ret = CRYPT_RSA_PrivateKeyDecode(&mcRsa, client_key_der_1024, keySz);
    if (ret != 0) {
        printf("mcapi rsa private key decode failed\n");
        return -1;
    }

    ret = RsaPrivateKeyDecode(client_key_der_1024, &idx, &defRsa, keySz);
    if (ret != 0) {
        printf("default rsa private key decode failed\n");
        return -1;
    }

    ret = CRYPT_RSA_PublicEncrypt(&mcRsa, out1, sizeof(out1), ourData,
                                  RSA_TEST_SIZE, &mcRng);
    if (ret < 0) {
        printf("mcapi rsa public encrypt failed\n");
        return -1;
    }

    ret2 = RsaPublicEncrypt(ourData, RSA_TEST_SIZE, out2, sizeof(out2),
                            &defRsa, &defRng);
    if (ret2 < 0) {
        printf("default rsa public encrypt failed\n");
        return -1;
    }

    if (ret != ret2) {
        printf("default rsa public encrypt sz != mcapi sz\n");
        return -1;
    }

    if (ret != CRYPT_RSA_EncryptSizeGet(&mcRsa)) {
        printf("mcapi encrypt sz get != mcapi sz\n");
        return -1;
    }

    ret = CRYPT_RSA_PrivateDecrypt(&mcRsa, out2, sizeof(out2), out1, ret); 
    if (ret < 0) {
        printf("mcapi rsa private derypt failed\n");
        return -1;
    }

    if (ret != RSA_TEST_SIZE) {
        printf("mcapi rsa private derypt plain size wrong\n");
        return -1;
    }

    if (memcmp(out2, ourData, ret) != 0) {
        printf("mcapi rsa private derypt plain text bad\n");
        return -1;
    }

    FreeRsaKey(&defRsa);
    ret = CRYPT_RSA_Free(&mcRsa);
    if (ret != 0) {
        printf("mcapi rsa free failed\n");
        return -1;
    }
    
    printf("rsa         mcapi test passed\n");

    return 0;
}
Ejemplo n.º 7
0
void bench_rsa(void)
{
    int    i;
    int    ret;
    byte   tmp[3072];
    size_t bytes;
    word32 idx = 0;

    byte      message[] = "Everyone gets Friday off.";
    byte      enc[512];  /* for up to 4096 bit */
    const int len = (int)strlen((char*)message);
    double    start, total, each, milliEach;
    
    RsaKey rsaKey;
    int    rsaKeySz = 2048; /* used in printf */

#ifdef USE_CERT_BUFFERS_1024
    XMEMCPY(tmp, rsa_key_der_1024, sizeof_rsa_key_der_1024);
    bytes = sizeof_rsa_key_der_1024;
    rsaKeySz = 1024;
#elif defined(USE_CERT_BUFFERS_2048)
    XMEMCPY(tmp, rsa_key_der_2048, sizeof_rsa_key_der_2048);
    bytes = sizeof_rsa_key_der_2048;
#else
    FILE*  file = fopen(certRSAname, "rb");

    if (!file) {
        printf("can't find %s, Please run from CyaSSL home dir\n", certRSAname);
        return;
    }
    
    bytes = fread(tmp, 1, sizeof(tmp), file);
    fclose(file);
#endif /* USE_CERT_BUFFERS */

		
#ifdef HAVE_CAVIUM
    if (RsaInitCavium(&rsaKey, CAVIUM_DEV_ID) != 0)
        printf("RSA init cavium failed\n");
#endif
    ret = InitRng(&rng);
    if (ret < 0) {
        printf("InitRNG failed\n");
        return;
    }
    ret = InitRsaKey(&rsaKey, 0);
    if (ret < 0) {
        printf("InitRsaKey failed\n");
        return;
    }
    ret = RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes);
    
    start = current_time(1);

    for (i = 0; i < ntimes; i++)
        ret = RsaPublicEncrypt(message,len,enc,sizeof(enc), &rsaKey, &rng);

    total = current_time(0) - start;
    each  = total / ntimes;   /* per second   */
    milliEach = each * 1000; /* milliseconds */

    printf("RSA %d encryption took %6.3f milliseconds, avg over %d"
           " iterations\n", rsaKeySz, milliEach, ntimes);

    if (ret < 0) {
        printf("Rsa Public Encrypt failed\n");
        return;
    }

    start = current_time(1);

    for (i = 0; i < ntimes; i++) {
         byte  out[512];  /* for up to 4096 bit */
         RsaPrivateDecrypt(enc, (word32)ret, out, sizeof(out), &rsaKey);
    }

    total = current_time(0) - start;
    each  = total / ntimes;   /* per second   */
    milliEach = each * 1000; /* milliseconds */

    printf("RSA %d decryption took %6.3f milliseconds, avg over %d"
           " iterations\n", rsaKeySz, milliEach, ntimes);

    FreeRsaKey(&rsaKey);
#ifdef HAVE_CAVIUM
    RsaFreeCavium(&rsaKey);
#endif
}
Ejemplo n.º 8
0
int rsa_test()
{
    byte   tmp[1024], tmp2[2048];
    size_t bytes, bytes2;
    RsaKey key;
    RNG    rng;
    word32 idx = 0;
    int    ret;
    byte   in[] = "Everyone gets Friday off.";
    word32 inLen = (word32)strlen((char*)in);
    byte   out[64];
    byte   plain[64];
    DecodedCert cert;

    FILE*  file = fopen(clientKey, "rb"), * file2;

    if (!file)
        return -40;

    bytes = fread(tmp, 1, 1024, file);
  
    InitRsaKey(&key, 0);  
    ret = RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes);
    if (ret != 0) return -41;

    ret = InitRng(&rng);
    if (ret != 0) return -42;

    ret = RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng);  

    ret = RsaPrivateDecrypt(out, 64, plain, sizeof(plain), &key);

    if (memcmp(plain, in, inLen)) return -45;

    ret = RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng);
    memset(plain, 0, sizeof(plain));
    ret = RsaSSL_Verify(out, 64, plain, sizeof(plain), &key);

    if (memcmp(plain, in, ret)) return -46;

    file2 = fopen(clientCert, "rb");
    if (!file2)
        return -47;

    bytes2 = fread(tmp2, 1, 2048, file2);

    InitDecodedCert(&cert, (byte*)&tmp2, 0);

    ret = ParseCert(&cert, (word32)bytes2, CERT_TYPE, NO_VERIFY, 0);
    if (ret != 0) return -48;

    FreeDecodedCert(&cert);

    fclose(file2);
    fclose(file);

#ifdef CYASSL_KEY_GEN
    {
        byte   der[4096];
        byte   pem[4096];
        word32 derSz = 0;
        word32 pemSz = 0;
        RsaKey derIn;
        RsaKey genKey;
        FILE* keyFile;
        FILE* pemFile;

        InitRsaKey(&genKey, 0);
        ret = MakeRsaKey(&genKey, 1024, 65537, &rng);
        if (ret != 0)
            return -301;

        derSz = RsaKeyToDer(&genKey, der, sizeof(der));
        if (derSz < 0)
            return -302;

        keyFile = fopen("./ker.der", "wb");
        if (!keyFile)
            return -303;
        ret = fwrite(der, derSz, 1, keyFile);
        fclose(keyFile);

        pemSz = DerToPem(der, derSz, pem, sizeof(pem), PRIVATEKEY_TYPE);
        if (pemSz < 0)
            return -304;

        pemFile = fopen("./key.pem", "wb");
        if (!pemFile) 
            return -305;
        ret = fwrite(pem, pemSz, 1, pemFile);
        fclose(pemFile);

        InitRsaKey(&derIn, 0);
        idx = 0;
        ret = RsaPrivateKeyDecode(der, &idx, &derIn, derSz);
        if (ret != 0)
            return -306;
    }
#endif /* CYASSL_KEY_GEN */


#ifdef CYASSL_CERT_GEN
    {
        Cert        myCert;
        byte        derCert[4096];
        byte        pem[4096];
        DecodedCert decode;
        FILE*       derFile;
        FILE*       pemFile;
        int         certSz;
        int         pemSz;

        InitCert(&myCert);

        strncpy(myCert.subject.country, "US", NAME_SIZE);
        strncpy(myCert.subject.state, "OR", NAME_SIZE);
        strncpy(myCert.subject.locality, "Portland", NAME_SIZE);
        strncpy(myCert.subject.org, "yaSSL", NAME_SIZE);
        strncpy(myCert.subject.unit, "Development", NAME_SIZE);
        strncpy(myCert.subject.commonName, "www.yassl.com", NAME_SIZE);
        strncpy(myCert.subject.email, "*****@*****.**", NAME_SIZE);

        certSz = MakeCert(&myCert, derCert, sizeof(derCert), &key, &rng); 
        if (certSz < 0)
            return -401;

        InitDecodedCert(&decode, derCert, 0);
        ret = ParseCert(&decode, certSz, CERT_TYPE, NO_VERIFY, 0);
        if (ret != 0)
            return -402;

        derFile = fopen("./cert.der", "wb");
        if (!derFile)
            return -403;
        ret = fwrite(derCert, certSz, 1, derFile);
        fclose(derFile);

        pemSz = DerToPem(derCert, certSz, pem, sizeof(pem), CERT_TYPE);
        if (pemSz < 0)
            return -404;

        pemFile = fopen("./cert.pem", "wb");
        if (!pemFile)
            return -405;
        ret = fwrite(pem, pemSz, 1, pemFile);
        fclose(pemFile);

        FreeDecodedCert(&decode);

    }
#endif /* CYASSL_CERT_GEN */

    FreeRsaKey(&key);

    return 0;
}
Ejemplo n.º 9
0
/* create ASN.1 fomatted RecipientInfo structure, returns sequence size */
CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz,
                                     int keyEncAlgo, int blockKeySz,
                                     RNG* rng, byte* contentKeyPlain,
                                     byte* contentKeyEnc,
                                     int* keyEncSz, byte* out, word32 outSz)
{
    word32 idx = 0;
    int ret = 0, totalSz = 0;
    int verSz, issuerSz, snSz, keyEncAlgSz;
    int issuerSeqSz, recipSeqSz, issuerSerialSeqSz;
    int encKeyOctetStrSz;

    byte ver[MAX_VERSION_SZ];
    byte serial[MAX_SN_SZ];
    byte issuerSerialSeq[MAX_SEQ_SZ];
    byte recipSeq[MAX_SEQ_SZ];
    byte issuerSeq[MAX_SEQ_SZ];
    byte keyAlgArray[MAX_ALGO_SZ];
    byte encKeyOctetStr[MAX_OCTET_STR_SZ];

    RsaKey pubKey;
    DecodedCert decoded;

    InitDecodedCert(&decoded, (byte*)cert, certSz, 0);
    ret = ParseCert(&decoded, CA_TYPE, NO_VERIFY, 0);
    if (ret < 0) {
        FreeDecodedCert(&decoded);
        return ret;
    }

    /* version */
    verSz = SetMyVersion(0, ver, 0);

    /* IssuerAndSerialNumber */
    if (decoded.issuerRaw == NULL || decoded.issuerRawLen == 0) {
        CYASSL_MSG("DecodedCert lacks raw issuer pointer and length");
        FreeDecodedCert(&decoded);
        return -1;
    }
    issuerSz    = decoded.issuerRawLen;
    issuerSeqSz = SetSequence(issuerSz, issuerSeq);

    if (decoded.serial == NULL || decoded.serialSz == 0) {
        CYASSL_MSG("DecodedCert missing serial number");
        FreeDecodedCert(&decoded);
        return -1;
    }
    snSz = SetSerialNumber(decoded.serial, decoded.serialSz, serial);

    issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz,
                                    issuerSerialSeq);

    /* KeyEncryptionAlgorithmIdentifier, only support RSA now */
    if (keyEncAlgo != RSAk)
        return ALGO_ID_E;

    keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0);
    if (keyEncAlgSz == 0)
        return BAD_FUNC_ARG;

    /* EncryptedKey */
    ret = InitRsaKey(&pubKey, 0);
    if (ret != 0) return ret;
    if (RsaPublicKeyDecode(decoded.publicKey, &idx, &pubKey,
                           decoded.pubKeySize) < 0) {
        CYASSL_MSG("ASN RSA key decode error");
        return PUBLIC_KEY_E;
    }

    *keyEncSz = RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc,
                                 MAX_ENCRYPTED_KEY_SZ, &pubKey, rng);
    FreeRsaKey(&pubKey);
    if (*keyEncSz < 0) {
        CYASSL_MSG("RSA Public Encrypt failed");
        return *keyEncSz;
    }

    encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr);

    /* RecipientInfo */
    recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz +
                             issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz +
                             *keyEncSz, recipSeq);

    if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz +
        keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) {
        CYASSL_MSG("RecipientInfo output buffer too small");
        return BUFFER_E;
    }

    XMEMCPY(out + totalSz, recipSeq, recipSeqSz);
    totalSz += recipSeqSz;
    XMEMCPY(out + totalSz, ver, verSz);
    totalSz += verSz;
    XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz);
    totalSz += issuerSerialSeqSz;
    XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz);
    totalSz += issuerSeqSz;
    XMEMCPY(out + totalSz, decoded.issuerRaw, issuerSz);
    totalSz += issuerSz;
    XMEMCPY(out + totalSz, serial, snSz);
    totalSz += snSz;
    XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz);
    totalSz += keyEncAlgSz;
    XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz);
    totalSz += encKeyOctetStrSz;
    XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz);
    totalSz += *keyEncSz;

    FreeDecodedCert(&decoded);

    return totalSz;
}
Ejemplo n.º 10
0
/* Finds the certificates in the message and saves it. */
int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
{
    word32 idx, contentType;
    int length, version, ret;
    byte* content = NULL;
    byte* sig = NULL;
    byte* cert = NULL;
    byte* signedAttr = NULL;
    int contentSz = 0, sigSz = 0, certSz = 0, signedAttrSz = 0;

    (void)signedAttr;    /* not used yet, just set */
    (void)signedAttrSz;

    if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
        return BAD_FUNC_ARG;

    idx = 0;

    /* Get the contentInfo sequence */
    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    /* Get the contentInfo contentType */
    if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (contentType != SIGNED_DATA) {
        CYASSL_MSG("PKCS#7 input not of type SignedData");
        return PKCS7_OID_E;
    }

    /* get the ContentInfo content */
    if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
        return ASN_PARSE_E;

    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    /* Get the signedData sequence */
    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    /* Get the version */
    if (GetMyVersion(pkiMsg, &idx, &version) < 0)
        return ASN_PARSE_E;

    if (version != 1) {
        CYASSL_MSG("PKCS#7 signedData needs to be of version 1");
        return ASN_VERSION_E;
    }

    /* Get the set of DigestAlgorithmIdentifiers */
    if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    /* Skip the set. */
    idx += length;

    /* Get the inner ContentInfo sequence */
    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    /* Get the inner ContentInfo contentType */
    if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (contentType != DATA) {
        CYASSL_MSG("PKCS#7 inner input not of type Data");
        return PKCS7_OID_E;
    }

    if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
        return ASN_PARSE_E;

    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (pkiMsg[idx++] != ASN_OCTET_STRING)
        return ASN_PARSE_E;

    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    /* Save the inner data as the content. */
    if (length > 0) {
        /* Local pointer for calculating hashes later */
        pkcs7->content = content = &pkiMsg[idx];
        pkcs7->contentSz = contentSz = length;
        idx += length;
    }

    /* Get the implicit[0] set of certificates */
    if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
        idx++;
        if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        if (length > 0) {
            /* At this point, idx is at the first certificate in
             * a set of certificates. There may be more than one,
             * or none, or they may be a PKCS 6 extended
             * certificate. We want to save the first cert if it
             * is X.509. */

            word32 certIdx = idx;

            if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
                if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0)
                    return ASN_PARSE_E;

                cert = &pkiMsg[idx];
                certSz += (certIdx - idx);
            }
            PKCS7_InitWithCert(pkcs7, cert, certSz);
        }
        idx += length;
    }

    /* Get the implicit[1] set of crls */
    if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
        idx++;
        if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        /* Skip the set */
        idx += length;
    }

    /* Get the set of signerInfos */
    if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (length > 0) {
        RsaKey key;
        word32 scratch = 0;
        int plainSz = 0;
        byte digest[MAX_SEQ_SZ+MAX_ALGO_SZ+MAX_OCTET_STR_SZ+SHA_DIGEST_SIZE];

        /* Get the sequence of the first signerInfo */
        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        /* Get the version */
        if (GetMyVersion(pkiMsg, &idx, &version) < 0)
            return ASN_PARSE_E;

        if (version != 1) {
            CYASSL_MSG("PKCS#7 signerInfo needs to be of version 1");
            return ASN_VERSION_E;
        }

        /* Get the sequence of IssuerAndSerialNumber */
        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        /* Skip it */
        idx += length;

        /* Get the sequence of digestAlgorithm */
        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        /* Skip it */
        idx += length;

        /* Get the IMPLICIT[0] SET OF signedAttributes */
        if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
            idx++;

            if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
                return ASN_PARSE_E;

            /* save pointer and length */
            signedAttr = &pkiMsg[idx];
            signedAttrSz = length;

            idx += length;
        }

        /* Get the sequence of digestEncryptionAlgorithm */
        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        /* Skip it */
        idx += length;

        /* Get the signature */
        if (pkiMsg[idx] == ASN_OCTET_STRING) {
            idx++;

            if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
                return ASN_PARSE_E;

            /* save pointer and length */
            sig = &pkiMsg[idx];
            sigSz = length;

            idx += length;
        }

        XMEMSET(digest, 0, sizeof(digest));
        pkcs7->content = content;
        pkcs7->contentSz = contentSz;

        ret = InitRsaKey(&key, NULL);
        if (ret != 0) return ret;
        if (RsaPublicKeyDecode(pkcs7->publicKey, &scratch, &key,
                               pkcs7->publicKeySz) < 0) {
            CYASSL_MSG("ASN RSA key decode error");
            return PUBLIC_KEY_E;
        }
        plainSz = RsaSSL_Verify(sig, sigSz, digest, sizeof(digest), &key);
        FreeRsaKey(&key);
        if (plainSz < 0)
            return plainSz;
    }

    return 0;
}
Ejemplo n.º 11
0
/* build PKCS#7 signedData content type */
int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
{
    static const byte outerOid[] =
        { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
                         0x07, 0x02 };
    static const byte innerOid[] =
        { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
                         0x07, 0x01 };

    ESD esd;
    word32 signerInfoSz = 0;
    word32 totalSz = 0;
    int idx = 0, ret = 0;
    byte* flatSignedAttribs = NULL;
    word32 flatSignedAttribsSz = 0;
    word32 innerOidSz = sizeof(innerOid);
    word32 outerOidSz = sizeof(outerOid);

    if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
        pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 ||
        pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 ||
        pkcs7->privateKey == NULL || pkcs7->privateKeySz == 0 ||
        output == NULL || outputSz == 0)
        return BAD_FUNC_ARG;

    XMEMSET(&esd, 0, sizeof(esd));
    ret = InitSha(&esd.sha);
    if (ret != 0)
        return ret;

    if (pkcs7->contentSz != 0)
    {
        ShaUpdate(&esd.sha, pkcs7->content, pkcs7->contentSz);
        esd.contentDigest[0] = ASN_OCTET_STRING;
        esd.contentDigest[1] = SHA_DIGEST_SIZE;
        ShaFinal(&esd.sha, &esd.contentDigest[2]);
    }

    esd.innerOctetsSz = SetOctetString(pkcs7->contentSz, esd.innerOctets);
    esd.innerContSeqSz = SetExplicit(0, esd.innerOctetsSz + pkcs7->contentSz,
                                esd.innerContSeq);
    esd.contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd.innerOctetsSz +
                                    innerOidSz + esd.innerContSeqSz,
                                    esd.contentInfoSeq);

    esd.issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
                                     esd.issuerSn);
    signerInfoSz += esd.issuerSnSz;
    esd.issuerNameSz = SetSequence(pkcs7->issuerSz, esd.issuerName);
    signerInfoSz += esd.issuerNameSz + pkcs7->issuerSz;
    esd.issuerSnSeqSz = SetSequence(signerInfoSz, esd.issuerSnSeq);
    signerInfoSz += esd.issuerSnSeqSz;
    esd.signerVersionSz = SetMyVersion(1, esd.signerVersion, 0);
    signerInfoSz += esd.signerVersionSz;
    esd.signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.signerDigAlgoId,
                                      hashType, 0);
    signerInfoSz += esd.signerDigAlgoIdSz;
    esd.digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd.digEncAlgoId,
                                   keyType, 0);
    signerInfoSz += esd.digEncAlgoIdSz;

    if (pkcs7->signedAttribsSz != 0) {
        byte contentTypeOid[] =
                { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
                                 0x09, 0x03 };
        byte contentType[] =
                { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
                                 0x07, 0x01 };
        byte messageDigestOid[] =
                { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
                                 0x09, 0x04 };

        PKCS7Attrib cannedAttribs[2] =
        {
            { contentTypeOid, sizeof(contentTypeOid),
                             contentType, sizeof(contentType) },
            { messageDigestOid, sizeof(messageDigestOid),
                             esd.contentDigest, sizeof(esd.contentDigest) }
        };
        word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);

        esd.signedAttribsCount += cannedAttribsCount;
        esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[0], 2,
                                             cannedAttribs, cannedAttribsCount);

        esd.signedAttribsCount += pkcs7->signedAttribsSz;
        esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[2], 4,
                                  pkcs7->signedAttribs, pkcs7->signedAttribsSz);

        flatSignedAttribs = (byte*)XMALLOC(esd.signedAttribsSz, 0, NULL);
        flatSignedAttribsSz = esd.signedAttribsSz;
        if (flatSignedAttribs == NULL)
            return MEMORY_E;
        FlattenAttributes(flatSignedAttribs,
                                     esd.signedAttribs, esd.signedAttribsCount);
        esd.signedAttribSetSz = SetImplicit(ASN_SET, 0, esd.signedAttribsSz,
                                                           esd.signedAttribSet);
    }
    /* Calculate the final hash and encrypt it. */
    {
        RsaKey privKey;
        int result;
        word32 scratch = 0;

        byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ +
                        MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE];
        byte digestInfoSeq[MAX_SEQ_SZ];
        byte digestStr[MAX_OCTET_STR_SZ];
        word32 digestInfoSeqSz, digestStrSz;
        int digIdx = 0;

        if (pkcs7->signedAttribsSz != 0) {
            byte attribSet[MAX_SET_SZ];
            word32 attribSetSz;

            attribSetSz = SetSet(flatSignedAttribsSz, attribSet);

            ret = InitSha(&esd.sha);
            if (ret < 0) {
                XFREE(flatSignedAttribs, 0, NULL);
                return ret;
            }
            ShaUpdate(&esd.sha, attribSet, attribSetSz);
            ShaUpdate(&esd.sha, flatSignedAttribs, flatSignedAttribsSz);
        }
        ShaFinal(&esd.sha, esd.contentAttribsDigest);

        digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr);
        digestInfoSeqSz = SetSequence(esd.signerDigAlgoIdSz +
                                      digestStrSz + SHA_DIGEST_SIZE,
                                      digestInfoSeq);

        XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
        digIdx += digestInfoSeqSz;
        XMEMCPY(digestInfo + digIdx,
                                    esd.signerDigAlgoId, esd.signerDigAlgoIdSz);
        digIdx += esd.signerDigAlgoIdSz;
        XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
        digIdx += digestStrSz;
        XMEMCPY(digestInfo + digIdx, esd.contentAttribsDigest, SHA_DIGEST_SIZE);
        digIdx += SHA_DIGEST_SIZE;

        result = InitRsaKey(&privKey, NULL);
        if (result == 0)
            result = RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, &privKey,
                                         pkcs7->privateKeySz);
        if (result < 0) {
            XFREE(flatSignedAttribs, 0, NULL);
            return PUBLIC_KEY_E;
        }
        result = RsaSSL_Sign(digestInfo, digIdx,
                             esd.encContentDigest, sizeof(esd.encContentDigest),
                             &privKey, pkcs7->rng);
        FreeRsaKey(&privKey);
        if (result < 0) {
            XFREE(flatSignedAttribs, 0, NULL);
            return result;
        }
        esd.encContentDigestSz = (word32)result;
    }
    signerInfoSz += flatSignedAttribsSz + esd.signedAttribSetSz;

    esd.signerDigestSz = SetOctetString(esd.encContentDigestSz,
                                                              esd.signerDigest);
    signerInfoSz += esd.signerDigestSz + esd.encContentDigestSz;

    esd.signerInfoSeqSz = SetSequence(signerInfoSz, esd.signerInfoSeq);
    signerInfoSz += esd.signerInfoSeqSz;
    esd.signerInfoSetSz = SetSet(signerInfoSz, esd.signerInfoSet);
    signerInfoSz += esd.signerInfoSetSz;

    esd.certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz, esd.certsSet);

    esd.singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.singleDigAlgoId,
                                      hashType, 0);
    esd.digAlgoIdSetSz = SetSet(esd.singleDigAlgoIdSz, esd.digAlgoIdSet);


    esd.versionSz = SetMyVersion(1, esd.version, 0);

    totalSz = esd.versionSz + esd.singleDigAlgoIdSz + esd.digAlgoIdSetSz +
              esd.contentInfoSeqSz + esd.certsSetSz + pkcs7->singleCertSz +
              esd.innerOctetsSz + esd.innerContSeqSz +
              innerOidSz + pkcs7->contentSz +
              signerInfoSz;
    esd.innerSeqSz = SetSequence(totalSz, esd.innerSeq);
    totalSz += esd.innerSeqSz;
    esd.outerContentSz = SetExplicit(0, totalSz, esd.outerContent);
    totalSz += esd.outerContentSz + outerOidSz;
    esd.outerSeqSz = SetSequence(totalSz, esd.outerSeq);
    totalSz += esd.outerSeqSz;

    if (outputSz < totalSz)
        return BUFFER_E;

    idx = 0;
    XMEMCPY(output + idx, esd.outerSeq, esd.outerSeqSz);
    idx += esd.outerSeqSz;
    XMEMCPY(output + idx, outerOid, outerOidSz);
    idx += outerOidSz;
    XMEMCPY(output + idx, esd.outerContent, esd.outerContentSz);
    idx += esd.outerContentSz;
    XMEMCPY(output + idx, esd.innerSeq, esd.innerSeqSz);
    idx += esd.innerSeqSz;
    XMEMCPY(output + idx, esd.version, esd.versionSz);
    idx += esd.versionSz;
    XMEMCPY(output + idx, esd.digAlgoIdSet, esd.digAlgoIdSetSz);
    idx += esd.digAlgoIdSetSz;
    XMEMCPY(output + idx, esd.singleDigAlgoId, esd.singleDigAlgoIdSz);
    idx += esd.singleDigAlgoIdSz;
    XMEMCPY(output + idx, esd.contentInfoSeq, esd.contentInfoSeqSz);
    idx += esd.contentInfoSeqSz;
    XMEMCPY(output + idx, innerOid, innerOidSz);
    idx += innerOidSz;
    XMEMCPY(output + idx, esd.innerContSeq, esd.innerContSeqSz);
    idx += esd.innerContSeqSz;
    XMEMCPY(output + idx, esd.innerOctets, esd.innerOctetsSz);
    idx += esd.innerOctetsSz;
    XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
    idx += pkcs7->contentSz;
    XMEMCPY(output + idx, esd.certsSet, esd.certsSetSz);
    idx += esd.certsSetSz;
    XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz);
    idx += pkcs7->singleCertSz;
    XMEMCPY(output + idx, esd.signerInfoSet, esd.signerInfoSetSz);
    idx += esd.signerInfoSetSz;
    XMEMCPY(output + idx, esd.signerInfoSeq, esd.signerInfoSeqSz);
    idx += esd.signerInfoSeqSz;
    XMEMCPY(output + idx, esd.signerVersion, esd.signerVersionSz);
    idx += esd.signerVersionSz;
    XMEMCPY(output + idx, esd.issuerSnSeq, esd.issuerSnSeqSz);
    idx += esd.issuerSnSeqSz;
    XMEMCPY(output + idx, esd.issuerName, esd.issuerNameSz);
    idx += esd.issuerNameSz;
    XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz);
    idx += pkcs7->issuerSz;
    XMEMCPY(output + idx, esd.issuerSn, esd.issuerSnSz);
    idx += esd.issuerSnSz;
    XMEMCPY(output + idx, esd.signerDigAlgoId, esd.signerDigAlgoIdSz);
    idx += esd.signerDigAlgoIdSz;

    /* SignerInfo:Attributes */
    if (pkcs7->signedAttribsSz != 0) {
        XMEMCPY(output + idx, esd.signedAttribSet, esd.signedAttribSetSz);
        idx += esd.signedAttribSetSz;
        XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz);
        idx += flatSignedAttribsSz;
        XFREE(flatSignedAttribs, 0, NULL);
    }

    XMEMCPY(output + idx, esd.digEncAlgoId, esd.digEncAlgoIdSz);
    idx += esd.digEncAlgoIdSz;
    XMEMCPY(output + idx, esd.signerDigest, esd.signerDigestSz);
    idx += esd.signerDigestSz;
    XMEMCPY(output + idx, esd.encContentDigest, esd.encContentDigestSz);
    idx += esd.encContentDigestSz;

    return idx;
}
Ejemplo n.º 12
0
/* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */
CYASSL_API int PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
                                         word32 pkiMsgSz, byte* output,
                                         word32 outputSz)
{
    int recipFound = 0;
    int ret, version, length;
    word32 savedIdx = 0, idx = 0;
    word32 contentType, encOID;
    byte   issuerHash[SHA_DIGEST_SIZE];
    mp_int serialNum;

    int encryptedKeySz, keySz;
    byte tmpIv[DES_BLOCK_SIZE];
    byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
    byte* decryptedKey = NULL;

    RsaKey privKey;
    int encryptedContentSz;
    byte padLen;
    byte* encryptedContent = NULL;

    if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
        pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL ||
        pkcs7->privateKeySz == 0)
        return BAD_FUNC_ARG;

    if (pkiMsg == NULL || pkiMsgSz == 0 ||
        output == NULL || outputSz == 0)
        return BAD_FUNC_ARG;

    /* load private key */
    ret = InitRsaKey(&privKey, 0);
    if (ret != 0) return ret;
    ret = RsaPrivateKeyDecode(pkcs7->privateKey, &idx, &privKey,
                              pkcs7->privateKeySz);
    if (ret != 0) {
        CYASSL_MSG("Failed to decode RSA private key");
        return ret;
    }

    idx = 0;

    /* read past ContentInfo, verify type is envelopedData */
    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (contentType != ENVELOPED_DATA) {
        CYASSL_MSG("PKCS#7 input not of type EnvelopedData");
        return PKCS7_OID_E;
    }

    if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
        return ASN_PARSE_E;

    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    /* remove EnvelopedData and version */
    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (GetMyVersion(pkiMsg, &idx, &version) < 0)
        return ASN_PARSE_E;

    if (version != 0) {
        CYASSL_MSG("PKCS#7 envelopedData needs to be of version 0");
        return ASN_VERSION_E;
    }

    /* walk through RecipientInfo set, find correct recipient */
    if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    savedIdx = idx;
    recipFound = 0;

    /* when looking for next recipient, use first sequence and version to
     * indicate there is another, if not, move on */
    while(recipFound == 0) {

        /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to
         * last good saved one */
        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
            idx = savedIdx;
            break;
        }

        if (GetMyVersion(pkiMsg, &idx, &version) < 0) {
            idx = savedIdx;
            break;
        }

        if (version != 0)
            return ASN_VERSION_E;

        /* remove IssuerAndSerialNumber */
        if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        /* if we found correct recipient, issuer hashes will match */
        if (XMEMCMP(issuerHash, pkcs7->issuerHash, SHA_DIGEST_SIZE) == 0) {
            recipFound = 1;
        }

        if (GetInt(&serialNum, pkiMsg, &idx, pkiMsgSz) < 0)
            return ASN_PARSE_E;
        mp_clear(&serialNum);

        if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        /* key encryption algorithm must be RSA for now */
        if (encOID != RSAk)
            return ALGO_ID_E;

        /* read encryptedKey */
        if (pkiMsg[idx++] != ASN_OCTET_STRING)
            return ASN_PARSE_E;

        if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0)
            return ASN_PARSE_E;

        if (recipFound == 1)
            XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz);
        idx += encryptedKeySz;

        /* update good idx */
        savedIdx = idx;
    }

    if (recipFound == 0) {
        CYASSL_MSG("No recipient found in envelopedData that matches input");
        return PKCS7_RECIP_E;
    }

    /* remove EncryptedContentInfo */
    if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */
    if (pkiMsg[idx++] != ASN_OCTET_STRING)
        return ASN_PARSE_E;

    if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    if (length != DES_BLOCK_SIZE) {
        CYASSL_MSG("Incorrect IV length, must be of DES_BLOCK_SIZE");
        return ASN_PARSE_E;
    }

    XMEMCPY(tmpIv, &pkiMsg[idx], length);
    idx += length;

    /* read encryptedContent, cont[0] */
    if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0))
        return ASN_PARSE_E;

    if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0)
        return ASN_PARSE_E;

    encryptedContent = XMALLOC(encryptedContentSz, NULL,
                               DYNAMIC_TYPE_TMP_BUFFER);

    XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);

    /* decrypt encryptedKey */
    keySz = RsaPrivateDecryptInline(encryptedKey, encryptedKeySz,
                                    &decryptedKey, &privKey);
    FreeRsaKey(&privKey);
    if (keySz <= 0)
        return keySz;

    /* decrypt encryptedContent */
    if (encOID == DESb) {
        Des des;
        ret = Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);

        if (ret == 0)
            Des_CbcDecrypt(&des, encryptedContent, encryptedContent,
                                 encryptedContentSz);

        if (ret != 0) {
            XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
            return ret;
        }
    }
    else if (encOID == DES3b) {
        Des3 des;
        ret = Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
        if (ret == 0)
            ret = Des3_CbcDecrypt(&des, encryptedContent, encryptedContent,
                                  encryptedContentSz);

        if (ret != 0) {
            XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
            return ret;
        }
    } else {
        CYASSL_MSG("Unsupported content encryption OID type");
        return ALGO_ID_E;
    }

    padLen = encryptedContent[encryptedContentSz-1];

    /* copy plaintext to output */
    XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);

    /* free memory, zero out keys */
    XMEMSET(encryptedKey, 0, MAX_ENCRYPTED_KEY_SZ);
    XMEMSET(encryptedContent, 0, encryptedContentSz);
    XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);

    return encryptedContentSz - padLen;
}