// 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); }
/* 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; }
/* 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; }