Exemplo n.º 1
0
        internal Pkcs12SafeContents(ContentInfoAsn contentInfoAsn)
        {
            IsReadOnly = true;

            switch (contentInfoAsn.ContentType)
            {
            case Oids.Pkcs7Encrypted:
                ConfidentialityMode = Pkcs12ConfidentialityMode.Password;
                _encrypted          = contentInfoAsn.Content;
                break;

            case Oids.Pkcs7Enveloped:
                ConfidentialityMode = Pkcs12ConfidentialityMode.PublicKey;
                _encrypted          = contentInfoAsn.Content;
                break;

            case Oids.Pkcs7Data:
                ConfidentialityMode = Pkcs12ConfidentialityMode.None;
                _bags = ReadBags(PkcsHelpers.DecodeOctetStringAsMemory(contentInfoAsn.Content));
                break;

            default:
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }
        }
Exemplo n.º 2
0
        public override Oid GetEncodedMessageType(byte[] encodedMessage)
        {
            AsnReader reader = new AsnReader(encodedMessage, AsnEncodingRules.BER);

            ContentInfoAsn contentInfo = AsnSerializer.Deserialize <ContentInfoAsn>(
                reader.GetEncodedValue(),
                AsnEncodingRules.BER);

            return(new Oid(contentInfo.ContentType));
        }
Exemplo n.º 3
0
        internal void Decode(ReadOnlyMemory <byte> encodedMessage)
        {
            // Windows (and thus NetFx) reads the leading data and ignores extra.
            // So use the Deserialize overload which doesn't throw on extra data.
            ContentInfoAsn contentInfo = AsnSerializer.Deserialize <ContentInfoAsn>(
                encodedMessage,
                AsnEncodingRules.BER,
                out int bytesRead);

            if (contentInfo.ContentType != Oids.Pkcs7Signed)
            {
                throw new CryptographicException(SR.Cryptography_Cms_InvalidMessageType);
            }

            // Hold a copy of the SignedData memory so we are protected against memory reuse by the caller.
            _heldData        = contentInfo.Content.ToArray();
            _signedData      = AsnSerializer.Deserialize <SignedDataAsn>(_heldData, AsnEncodingRules.BER);
            _contentType     = _signedData.EncapContentInfo.ContentType;
            _hasPkcs7Content = false;

            if (!Detached)
            {
                ReadOnlyMemory <byte>?content = _signedData.EncapContentInfo.Content;
                ReadOnlyMemory <byte> contentValue;

                if (content.HasValue)
                {
                    contentValue = GetContent(content.Value, _contentType);
                    // If no OCTET STRING was stripped off, we have PKCS7 interop concerns.
                    _hasPkcs7Content = content.Value.Length == contentValue.Length;
                }
                else
                {
                    contentValue = ReadOnlyMemory <byte> .Empty;
                }

                // This is in _heldData, so we don't need a defensive copy.
                _heldContent = contentValue;

                // The ContentInfo object/property DOES need a defensive copy, because
                // a) it is mutable by the user, and
                // b) it is no longer authoritative
                //
                // (and c: it takes a byte[] and we have a ReadOnlyMemory<byte>)
                ContentInfo = new ContentInfo(new Oid(_contentType), contentValue.ToArray());
            }
            else
            {
                // Hold a defensive copy of the content bytes, (Windows/NetFx compat)
                _heldContent = ContentInfo.Content.CloneByteArray();
            }

            Version  = _signedData.Version;
            _hasData = true;
        }
Exemplo n.º 4
0
        public void Decode(byte[] encodedMessage)
        {
            if (encodedMessage == null)
            {
                throw new ArgumentNullException(nameof(encodedMessage));
            }

            // Windows (and thus NetFx) reads the leading data and ignores extra.
            // The deserializer will complain if too much data is given, so use the reader
            // to ask how much we want to deserialize.
            AsnReader             reader     = new AsnReader(encodedMessage, AsnEncodingRules.BER);
            ReadOnlyMemory <byte> cmsSegment = reader.GetEncodedValue();

            ContentInfoAsn contentInfo = AsnSerializer.Deserialize <ContentInfoAsn>(cmsSegment, AsnEncodingRules.BER);

            if (contentInfo.ContentType != Oids.Pkcs7Signed)
            {
                throw new CryptographicException(SR.Cryptography_Cms_InvalidMessageType);
            }

            // Hold a copy of the SignedData memory so we are protected against memory reuse by the caller.
            _heldData    = contentInfo.Content.ToArray();
            _signedData  = AsnSerializer.Deserialize <SignedDataAsn>(_heldData, AsnEncodingRules.BER);
            _contentType = _signedData.EncapContentInfo.ContentType;

            if (!Detached)
            {
                ReadOnlyMemory <byte>?content = _signedData.EncapContentInfo.Content;

                // This is in _heldData, so we don't need a defensive copy.
                _heldContent = content ?? ReadOnlyMemory <byte> .Empty;

                // The ContentInfo object/property DOES need a defensive copy, because
                // a) it is mutable by the user, and
                // b) it is no longer authoritative
                //
                // (and c: it takes a byte[] and we have a ReadOnlyMemory<byte>)
                ContentInfo = new ContentInfo(new Oid(_contentType), _heldContent.Value.ToArray());
            }
            else
            {
                // Hold a defensive copy of the content bytes, (Windows/NetFx compat)
                _heldContent = ContentInfo.Content.CloneByteArray();
            }

            Version  = _signedData.Version;
            _hasData = true;
        }
Exemplo n.º 5
0
        internal static byte[] EncodeContentInfo(
            ReadOnlyMemory <byte> content,
            string contentType,
            AsnEncodingRules ruleSet = AsnEncodingRules.DER)
        {
            ContentInfoAsn contentInfo = new ContentInfoAsn
            {
                ContentType = contentType,
                Content     = content,
            };

            AsnWriter writer = new AsnWriter(ruleSet);

            contentInfo.Encode(writer);
            return(writer.Encode());
        }
Exemplo n.º 6
0
        internal static byte[] EncodeContentInfo <T>(
            T value,
            string contentType,
            AsnEncodingRules ruleSet = AsnEncodingRules.DER)
        {
            using (AsnWriter innerWriter = AsnSerializer.Serialize(value, ruleSet))
            {
                ContentInfoAsn content = new ContentInfoAsn
                {
                    ContentType = contentType,
                    Content     = innerWriter.Encode(),
                };

                using (AsnWriter outerWriter = AsnSerializer.Serialize(content, ruleSet))
                {
                    return(outerWriter.Encode());
                }
            }
        }
Exemplo n.º 7
0
        public override Oid GetEncodedMessageType(byte[] encodedMessage)
        {
            AsnReader reader = new AsnReader(encodedMessage, AsnEncodingRules.BER);

            ContentInfoAsn.Decode(reader, out ContentInfoAsn contentInfo);

            switch (contentInfo.ContentType)
            {
            case Oids.Pkcs7Data:
            case Oids.Pkcs7Signed:
            case Oids.Pkcs7Enveloped:
            case Oids.Pkcs7SignedEnveloped:
            case Oids.Pkcs7Hashed:
            case Oids.Pkcs7Encrypted:
                return(new Oid(contentInfo.ContentType));
            }

            throw new CryptographicException(SR.Cryptography_Cms_InvalidMessageType);
        }
Exemplo n.º 8
0
        public byte[] Encode()
        {
            if (!_hasData)
            {
                throw new InvalidOperationException(SR.Cryptography_Cms_MessageNotSigned);
            }

            // Write as DER, so everyone can read it.
            AsnWriter writer = AsnSerializer.Serialize(_signedData, AsnEncodingRules.DER);

            byte[] signedData = writer.Encode();

            ContentInfoAsn contentInfo = new ContentInfoAsn
            {
                Content     = signedData,
                ContentType = Oids.Pkcs7Signed,
            };

            // Write as DER, so everyone can read it.
            writer = AsnSerializer.Serialize(contentInfo, AsnEncodingRules.DER);
            return(writer.Encode());
        }
Exemplo n.º 9
0
        public static Pkcs12Info Decode(
            ReadOnlyMemory <byte> encodedBytes,
            out int bytesConsumed,
            bool skipCopy = false)
        {
            AsnReader reader = new AsnReader(encodedBytes, AsnEncodingRules.BER);

            // Trim it to the first value
            encodedBytes = reader.PeekEncodedValue();

            ReadOnlyMemory <byte> maybeCopy = skipCopy ? encodedBytes : encodedBytes.ToArray();
            PfxAsn pfx = PfxAsn.Decode(maybeCopy, AsnEncodingRules.BER);

            // https://tools.ietf.org/html/rfc7292#section-4 only defines version 3.
            if (pfx.Version != 3)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            ReadOnlyMemory <byte> authSafeBytes = ReadOnlyMemory <byte> .Empty;
            Pkcs12IntegrityMode   mode          = Pkcs12IntegrityMode.Unknown;

            if (pfx.AuthSafe.ContentType == Oids.Pkcs7Data)
            {
                authSafeBytes = PkcsHelpers.DecodeOctetStringAsMemory(pfx.AuthSafe.Content);

                if (pfx.MacData.HasValue)
                {
                    mode = Pkcs12IntegrityMode.Password;
                }
                else
                {
                    mode = Pkcs12IntegrityMode.None;
                }
            }
            else if (pfx.AuthSafe.ContentType == Oids.Pkcs7Signed)
            {
                SignedDataAsn signedData = SignedDataAsn.Decode(pfx.AuthSafe.Content, AsnEncodingRules.BER);

                mode = Pkcs12IntegrityMode.PublicKey;

                if (signedData.EncapContentInfo.ContentType == Oids.Pkcs7Data)
                {
                    authSafeBytes = signedData.EncapContentInfo.Content.GetValueOrDefault();
                }

                if (pfx.MacData.HasValue)
                {
                    throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                }
            }

            if (mode == Pkcs12IntegrityMode.Unknown)
            {
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            List <ContentInfoAsn> authSafeData   = new List <ContentInfoAsn>();
            AsnReader             authSafeReader = new AsnReader(authSafeBytes, AsnEncodingRules.BER);
            AsnReader             sequenceReader = authSafeReader.ReadSequence();

            authSafeReader.ThrowIfNotEmpty();
            while (sequenceReader.HasData)
            {
                ContentInfoAsn.Decode(sequenceReader, out ContentInfoAsn contentInfo);
                authSafeData.Add(contentInfo);
            }

            ReadOnlyCollection <Pkcs12SafeContents> authSafe;

            if (authSafeData.Count == 0)
            {
                authSafe = new ReadOnlyCollection <Pkcs12SafeContents>(Array.Empty <Pkcs12SafeContents>());
            }
            else
            {
                Pkcs12SafeContents[] contentsArray = new Pkcs12SafeContents[authSafeData.Count];

                for (int i = 0; i < contentsArray.Length; i++)
                {
                    contentsArray[i] = new Pkcs12SafeContents(authSafeData[i]);
                }

                authSafe = new ReadOnlyCollection <Pkcs12SafeContents>(contentsArray);
            }

            bytesConsumed = encodedBytes.Length;

            return(new Pkcs12Info
            {
                AuthenticatedSafe = authSafe,
                IntegrityMode = mode,
                _decoded = pfx,
                _authSafeContents = authSafeBytes,
            });
        }
Exemplo n.º 10
0
        public static bool TryDecode(ReadOnlyMemory <byte> source, out Rfc3161TimestampToken token, out int bytesConsumed)
        {
            bytesConsumed = 0;
            token         = null;

            try
            {
                ContentInfoAsn contentInfo =
                    AsnSerializer.Deserialize <ContentInfoAsn>(source, AsnEncodingRules.BER, out int bytesActuallyRead);

                // https://tools.ietf.org/html/rfc3161#section-2.4.2
                //
                // A TimeStampToken is as follows.  It is defined as a ContentInfo
                // ([CMS]) and SHALL encapsulate a signed data content type.
                //
                // TimeStampToken::= ContentInfo
                //   --contentType is id-signedData([CMS])
                //   --content is SignedData ([CMS])
                if (contentInfo.ContentType != Oids.Pkcs7Signed)
                {
                    return(false);
                }

                SignedCms cms = new SignedCms();
                cms.Decode(source);

                // The fields of type EncapsulatedContentInfo of the SignedData
                // construct have the following meanings:
                //
                // eContentType is an object identifier that uniquely specifies the
                // content type.  For a time-stamp token it is defined as:
                //
                // id-ct-TSTInfo  OBJECT IDENTIFIER ::= { iso(1) member-body(2)
                // us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 4}
                //
                // eContent is the content itself, carried as an octet string.
                // The eContent SHALL be the DER-encoded value of TSTInfo.
                if (cms.ContentInfo.ContentType.Value != Oids.TstInfo)
                {
                    return(false);
                }

                // RFC3161:
                // The time-stamp token MUST NOT contain any signatures other than the
                // signature of the TSA.  The certificate identifier (ESSCertID) of the
                // TSA certificate MUST be included as a signerInfo attribute inside a
                // SigningCertificate attribute.

                // RFC5816 says that ESSCertIDv2 should be allowed instead.

                SignerInfoCollection signerInfos = cms.SignerInfos;

                if (signerInfos.Count != 1)
                {
                    return(false);
                }

                SignerInfo  signer = signerInfos[0];
                EssCertId   certId;
                EssCertIdV2 certId2;

                if (!TryGetCertIds(signer, out certId, out certId2))
                {
                    return(false);
                }

                X509Certificate2 signerCert = signer.Certificate;

                if (signerCert == null &&
                    signer.SignerIdentifier.Type == SubjectIdentifierType.IssuerAndSerialNumber)
                {
                    // If the cert wasn't provided, but the identifier was IssuerAndSerialNumber,
                    // and the ESSCertId(V2) has specified an issuerSerial value, ensure it's a match.
                    X509IssuerSerial issuerSerial = (X509IssuerSerial)signer.SignerIdentifier.Value;

                    if (certId?.IssuerSerial != null)
                    {
                        if (!IssuerAndSerialMatch(
                                certId.IssuerSerial.Value,
                                issuerSerial.IssuerName,
                                issuerSerial.SerialNumber))
                        {
                            return(false);
                        }
                    }

                    if (certId2?.IssuerSerial != null)
                    {
                        if (!IssuerAndSerialMatch(
                                certId2.IssuerSerial.Value,
                                issuerSerial.IssuerName,
                                issuerSerial.SerialNumber))
                        {
                            return(false);
                        }
                    }
                }

                Rfc3161TimestampTokenInfo tokenInfo;

                if (Rfc3161TimestampTokenInfo.TryDecode(cms.ContentInfo.Content, out tokenInfo, out _))
                {
                    if (signerCert != null &&
                        !CheckCertificate(signerCert, signer, certId, certId2, tokenInfo))
                    {
                        return(false);
                    }

                    token = new Rfc3161TimestampToken
                    {
                        _parsedDocument = cms,
                        _signerInfo     = signer,
                        _essCertId      = certId,
                        _essCertIdV2    = certId2,
                        TokenInfo       = tokenInfo,
                    };

                    bytesConsumed = bytesActuallyRead;
                    return(true);
                }
            }
            catch (CryptographicException)
            {
            }

            return(false);
        }
Exemplo n.º 11
0
        public override DecryptorPal Decode(
            byte[] encodedMessage,
            out int version,
            out ContentInfo contentInfo,
            out AlgorithmIdentifier contentEncryptionAlgorithm,
            out X509Certificate2Collection originatorCerts,
            out CryptographicAttributeObjectCollection unprotectedAttributes)
        {
            // Read using BER because the CMS specification says the encoding is BER.
            AsnReader reader = new AsnReader(encodedMessage, AsnEncodingRules.BER);

            ContentInfoAsn.Decode(
                reader,
                out ContentInfoAsn parsedContentInfo);

            if (parsedContentInfo.ContentType != Oids.Pkcs7Enveloped)
            {
                throw new CryptographicException(SR.Cryptography_Cms_InvalidMessageType);
            }

            byte[] copy = parsedContentInfo.Content.ToArray();

            EnvelopedDataAsn data = EnvelopedDataAsn.Decode(copy, AsnEncodingRules.BER);

            version = data.Version;

            contentInfo = new ContentInfo(
                new Oid(data.EncryptedContentInfo.ContentType),
                data.EncryptedContentInfo.EncryptedContent?.ToArray() ?? Array.Empty <byte>());

            contentEncryptionAlgorithm =
                data.EncryptedContentInfo.ContentEncryptionAlgorithm.ToPresentationObject();

            originatorCerts = new X509Certificate2Collection();

            if (data.OriginatorInfo.HasValue && data.OriginatorInfo.Value.CertificateSet != null)
            {
                foreach (CertificateChoiceAsn certChoice in data.OriginatorInfo.Value.CertificateSet)
                {
                    if (certChoice.Certificate != null)
                    {
                        originatorCerts.Add(new X509Certificate2(certChoice.Certificate.Value.ToArray()));
                    }
                }
            }

            unprotectedAttributes = SignerInfo.MakeAttributeCollection(data.UnprotectedAttributes);

            var recipientInfos = new List <RecipientInfo>();

            foreach (RecipientInfoAsn recipientInfo in data.RecipientInfos)
            {
                if (recipientInfo.Ktri.HasValue)
                {
                    recipientInfos.Add(new KeyTransRecipientInfo(new ManagedKeyTransPal(recipientInfo.Ktri.Value)));
                }
                else if (recipientInfo.Kari.HasValue)
                {
                    for (int i = 0; i < recipientInfo.Kari.Value.RecipientEncryptedKeys.Length; i++)
                    {
                        recipientInfos.Add(
                            new KeyAgreeRecipientInfo(new ManagedKeyAgreePal(recipientInfo.Kari.Value, i)));
                    }
                }
                else
                {
                    Debug.Fail($"{nameof(RecipientInfoAsn)} deserialized with an unknown recipient type");
                    throw new CryptographicException();
                }
            }

            return(new ManagedDecryptorPal(copy, data, new RecipientInfoCollection(recipientInfos)));
        }