| // Copyright 2026 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #ifndef THIRD_PARTY_CREDENTIO_CRYPTO_DEFAULT_CMS_CMS_PARSER_H_ |
| #define THIRD_PARTY_CREDENTIO_CRYPTO_DEFAULT_CMS_CMS_PARSER_H_ |
| |
| #include <cstddef> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "crypto/default/cms/cms_error_code.h" |
| #include "openssl/bytestring.h" |
| |
| namespace credentio_cms { |
| |
| // Class making sure that the CRYPTO ByteString used are always initialized. |
| class ByteString { |
| public: |
| ByteString() { CBS_init(&cbs_, nullptr, 0); } |
| CBS* cbs_ptr() { return &cbs_; } |
| const CBS* cbs_ptr() const { return &cbs_; } |
| const CBS& cbs() const { return cbs_; } |
| |
| private: |
| CBS cbs_; |
| }; |
| |
| // https://tools.ietf.org/html/rfc5280#section-4.1.1.2 |
| struct AlgorithmIdentifier { |
| ByteString algorithm_oid; |
| ByteString parameter; |
| // The un-parsed bytes so that d2i_X509_ALGOR can be used. |
| ByteString raw_value; |
| }; |
| |
| // https://tools.ietf.org/html/rfc5652#section-6.2.2 |
| struct OriginatorIdentifierOrKey { |
| // The issuer name and serial numbers are used if the subject_key_identifier |
| // is not set. |
| ByteString issuer_name; |
| ByteString serial_number; |
| ByteString subject_key_identifier; |
| AlgorithmIdentifier public_key_algorithm; |
| ByteString public_key_value; |
| }; |
| |
| // https://tools.ietf.org/html/rfc5652#section-6.2.2 |
| struct RecipientEncryptedKey { |
| // The issuer name and serial numbers are used if the subject_key_identifier |
| // is not set. |
| ByteString issuer_name; |
| ByteString serial_number; |
| ByteString subject_key_identifier; |
| // Optional |
| ByteString date; |
| // Optional OtherKeyAttribute from the RecipientKeyIdentifier. |
| ByteString other; |
| ByteString encrypted_key; |
| }; |
| |
| // https://tools.ietf.org/html/rfc5652#section-5.3 |
| // Signed or unsigned attribute. |
| struct Attribute { |
| ByteString type; |
| std::vector<ByteString> values; |
| }; |
| |
| // https://tools.ietf.org/html/rfc5751#section-2.5.3 |
| struct SmimeEncryptionKeyPreference { |
| // If the SMIMEEncryptionKeyPreference is not present all the fields will be |
| // empty. |
| ByteString issuer_name; |
| ByteString serial_number; |
| ByteString subject_key_identifier; |
| // Optional |
| ByteString date; |
| // Optional OtherKeyAttribute from the RecipientKeyIdentifier. |
| ByteString other; |
| }; |
| |
| struct SignerInfo { |
| int version; |
| // The issuer name and serial numbers are used if the subject_key_identifier |
| // is not set. |
| ByteString issuer_name; |
| ByteString serial_number; |
| ByteString subject_key_identifier; |
| AlgorithmIdentifier digest_algorithm; |
| ByteString raw_signed_attributes; |
| ByteString raw_unsigned_attributes; |
| // The 'message_digest' and 'content_type_signed' fields are extracted from |
| // the signed attributes (if present). |
| ByteString message_digest; |
| ByteString content_type_signed; |
| // All the signed attributes other than message digest and content type. |
| std::vector<Attribute> signed_attributes; |
| std::vector<Attribute> unsigned_attributes; |
| |
| AlgorithmIdentifier signature_algorithm; |
| ByteString signature_value; |
| SmimeEncryptionKeyPreference encryption_key_preference; |
| }; |
| |
| // https://tools.ietf.org/html/rfc5652#section-6.2.1 |
| struct RecipientInfo { |
| int version; |
| OriginatorIdentifierOrKey originator_identifier_or_key; |
| // Used for some key agreement algorithms. |
| ByteString user_keying_material; |
| AlgorithmIdentifier key_encryption_algorithm; |
| std::vector<RecipientEncryptedKey> encrypted_keys; |
| }; |
| |
| // https://tools.ietf.org/html/rfc5652#section-11.1 |
| enum class ContentType { |
| // Using the last digit of the OID defined in RFC 2315 section 14 as the enum |
| // value. |
| DATA = 1, |
| SIGNED_DATA = 2, |
| ENVELOPED_DATA = 3, |
| SIGNED_AND_ENVELOPED_DATA = 4, |
| DIGESTED_DATA = 5, |
| ENCRYPTED_DATA = 6 |
| }; |
| |
| struct Content { |
| enum ContentType type; |
| int version; |
| std::vector<AlgorithmIdentifier> digest_algorithms; |
| // The encapsulated_content_info.type for signed data, |
| // encrypted_content_info.type for enveloped data. |
| ByteString content_type; |
| // The content can be absent, for example in detached signatures, or it |
| // can be in one or more chunks. |
| std::vector<ByteString> content; |
| // ASN.1 tag of the content (CBS_ASN1_OCTETSTRING, etc.) |
| unsigned content_tag; |
| // The byte stream offsets of the first content tag byte and the first byte |
| // after the content. |
| std::pair<size_t, size_t> content_offsets; |
| // The encryption_algorithm_identifier and encryption_algorithm_iv are used |
| // for enveloped data. |
| AlgorithmIdentifier encryption_algorithm; |
| std::vector<ByteString> certificates; |
| std::vector<SignerInfo> signers; |
| std::vector<RecipientInfo> recipients; |
| }; |
| |
| // Zero copy CMS parser. |
| // |
| // - 'data' and 'size' should point to the binary data. This data must remain |
| // valid as long |
| // as 'contents' is used. |
| // - 'contents' is a view into the data and is only valid if the function |
| // returns ErrorCode::OK. |
| ErrorCode ParseCms(const char* data, size_t size, Content* contents, |
| std::string* error_message); |
| |
| } // namespace credentio_cms |
| |
| #endif // THIRD_PARTY_CREDENTIO_CRYPTO_DEFAULT_CMS_CMS_PARSER_H_ |