/* RSA Public key decode ASN.1 */ int CRYPT_RSA_PublicKeyDecode(CRYPT_RSA_CTX* rsa, const unsigned char* in, unsigned int inSz) { unsigned int idx = 0; (void)idx; if (rsa == NULL || in == NULL) return BAD_FUNC_ARG; return RsaPublicKeyDecode(in, &idx, (RsaKey*)rsa->holder, inSz); }
/* 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; }
/* 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; }