// Read public key
void CertDecoder::GetKey()
{
    if (source_.GetError().What()) return;

    GetSequence();    
    keyOID_ = GetAlgoId();

    if (keyOID_ == RSAk) {
        byte b = source_.next();
        if (b != BIT_STRING) {
            source_.SetError(BIT_STR_E);
            return;
        }
        b = source_.next();      // length, future
        b = source_.next(); 
        while(b != 0)
            b = source_.next();
    }
    else if (keyOID_ == DSAk)
        ;   // do nothing
    else {
        source_.SetError(UNKNOWN_OID_E);
        return;
    }

    StoreKey();
    if (keyOID_ == DSAk)
        AddDSA();
}
void CertDecoder::DecodeToKey()
{
    ReadHeader();
    signatureOID_ = GetAlgoId();
    GetName(ISSUER);   
    GetValidity();
    GetName(SUBJECT);   
    GetKey();
}
// Decode a x509v3 Certificate
void CertDecoder::Decode(SignerList* signers, CertType ct)
{
    if (source_.GetError().What()) return;
    DecodeToKey();
    if (source_.GetError().What()) return;

    if (source_.get_index() != sigIndex_)
        source_.set_index(sigIndex_);

    word32 confirmOID = GetAlgoId();
    GetSignature();
    if (source_.GetError().What()) return;

    if ( confirmOID != signatureOID_ ) {
        source_.SetError(SIG_OID_E);
        return;
    }

    if (ct != CA && verify_ && !ValidateSignature(signers))
            source_.SetError(SIG_OTHER_E);
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
/* optional mac data */
static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx,
                       word32 totalSz)
{
    MacData* mac;
    word32 curIdx = *idx;
    word32 oid = 0;
    int size, ret;


    /* Digest Info : Sequence
     *      DigestAlgorithmIdentifier
     *      Digest
     */
    if ((ret = GetSequence(mem, &curIdx, &size, totalSz)) <= 0) {
        WOLFSSL_MSG("Failed to get PKCS12 sequence");
        return ret;
    }

#ifdef WOLFSSL_DEBUG_PKCS12
    printf("\t\tSEQUENCE: DigestInfo size = %d\n", size);
#endif

    mac = (MacData*)XMALLOC(sizeof(MacData), pkcs12->heap, DYNAMIC_TYPE_PKCS);
    if (mac == NULL) {
        return MEMORY_E;
    }
    XMEMSET(mac, 0, sizeof(MacData));

    /* DigestAlgorithmIdentifier */
    if ((ret = GetAlgoId(mem, &curIdx, &oid, oidIgnoreType, totalSz)) < 0) {
        WOLFSSL_MSG("Failed to get PKCS12 sequence");
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        return ret;
    }
    mac->oid = oid;

    #ifdef WOLFSSL_DEBUG_PKCS12
    printf("\t\tALGO ID = %d\n", oid);
    #endif

    /* Digest: should be octet type holding digest */
    if (mem[curIdx++] != ASN_OCTET_STRING) {
        WOLFSSL_MSG("Failed to get digest");
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        return ASN_PARSE_E;
    }

    if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) {
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        return ret;
    }
    mac->digestSz = size;
    mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap,
                                 DYNAMIC_TYPE_PKCS);
    if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) {
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        return MEMORY_E;
    }
    XMEMCPY(mac->digest, mem + curIdx, mac->digestSz);
    #ifdef WOLFSSL_DEBUG_PKCS12
    {
        byte* p;
        for (printf("\t\tDigest = "), p = (byte*)mem+curIdx;
             p < (byte*)mem + curIdx + mac->digestSz;
             printf("%02X", *p), p++);
        printf(" : size = %d\n", mac->digestSz);
    }
    #endif
    curIdx += mac->digestSz;

    /* get salt, should be octet string */
    if (mem[curIdx++] != ASN_OCTET_STRING) {
        WOLFSSL_MSG("Failed to get salt");
        XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        return ASN_PARSE_E;
    }

    if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) {
        XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        return ret;
    }
    mac->saltSz = size;
    mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap,
                                 DYNAMIC_TYPE_PKCS);
    if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) {
        XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS);
        return MEMORY_E;
    }
    XMEMCPY(mac->salt, mem + curIdx, mac->saltSz);
    #ifdef WOLFSSL_DEBUG_PKCS12
    {
        byte* p;
        for (printf("\t\tSalt = "), p = (byte*)mem + curIdx;
             p < (byte*)mem + curIdx + mac->saltSz;
             printf("%02X", *p), p++);
        printf(" : size = %d\n", mac->saltSz);
    }
    #endif
    curIdx += mac->saltSz;

    /* check for MAC itterations, default to 1 */
    mac->itt = 1;
    if (curIdx < totalSz) {
        int number = 0;
        if ((ret = GetShortInt(mem, &curIdx, &number, totalSz)) >= 0) {
            /* found a itteration value */
            mac->itt = number;
        }
    }

#ifdef WOLFSSL_DEBUG_PKCS12
    printf("\t\tITTERATIONS : %d\n", mac->itt);
#endif

    *idx = curIdx;
    pkcs12->signData = mac;

    return 0;
}