/// <summary>
            ///         ImportParameters will replace the existing key that ECDsaOpenSsl is working with by creating a
            ///         new key. If the parameters contains only Q, then only a public key will be imported.
            ///         If the parameters also contains D, then a full key pair will be imported. 
            ///         The parameters Curve value specifies the type of the curve to import.
            /// </summary>
            /// <param name="parameters">The curve parameters.</param>
            /// <exception cref="CryptographicException">
            ///     if <paramref name="parameters" /> does not contain valid values.
            /// </exception>
            /// <exception cref="NotSupportedException">
            ///     if <paramref name="parameters" /> references a curve that cannot be imported.
            /// </exception>
            /// <exception cref="PlatformNotSupportedException">
            ///     if <paramref name="parameters" /> references a curve that is not supported by this platform.
            /// </exception>
            public override void ImportParameters(ECParameters parameters)
            {
                SafeEcKeyHandle key;

                parameters.Validate();

                if (parameters.Curve.IsPrime)
                {
                    key = ImportPrimeCurveParameters(parameters);
                }
                else if (parameters.Curve.IsCharacteristic2)
                {
                    key = ImportCharacteristic2CurveParameters(parameters);
                }
                else if (parameters.Curve.IsNamed)
                {
                    key = ImportNamedCurveParameters(parameters);
                }
                else
                {
                    throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, parameters.Curve.CurveType.ToString()));
                }

                if (key == null || key.IsInvalid)
                    throw Interop.Crypto.CreateOpenSslCryptographicException();

                SetKey(key);
            }
Esempio n. 2
0
        internal static byte[] GetNamedCurveBlob(ref ECParameters parameters)
        {
            Debug.Assert(parameters.Curve.IsNamed);

            bool includePrivateParameters = (parameters.D != null);
            byte[] blob;
            unsafe
            {
                // We need to build a key blob structured as follows:
                //     BCRYPT_ECCKEY_BLOB   header
                //     byte[cbKey]          Q.X
                //     byte[cbKey]          Q.Y
                //     -- Only if "includePrivateParameters" is true --
                //     byte[cbKey]          D

                int blobSize = sizeof(BCRYPT_ECCKEY_BLOB) +
                    parameters.Q.X.Length +
                    parameters.Q.Y.Length;
                if (includePrivateParameters)
                {
                    blobSize += parameters.D.Length;
                }

                blob = new byte[blobSize];
                fixed (byte* pBlob = blob)
                {
                    // Build the header
                    BCRYPT_ECCKEY_BLOB* pBcryptBlob = (BCRYPT_ECCKEY_BLOB*)pBlob;
                    pBcryptBlob->Magic = CurveNameToMagicNumber(parameters.Curve.Oid.FriendlyName, includePrivateParameters);
                    pBcryptBlob->cbKey = parameters.Q.X.Length;

                    // Emit the blob
                    int offset = sizeof(BCRYPT_ECCKEY_BLOB);
                    Interop.BCrypt.Emit(blob, ref offset, parameters.Q.X);
                    Interop.BCrypt.Emit(blob, ref offset, parameters.Q.Y);
                    if (includePrivateParameters)
                    {
                        Interop.BCrypt.Emit(blob, ref offset, parameters.D);
                    }

                    // We better have computed the right allocation size above!
                    Debug.Assert(offset == blobSize, "offset == blobSize");
                }
            }
            return blob;
        }
Esempio n. 3
0
        private static Track2Sdk.JsonWebKey CreateTrack2SdkJWK(ECDsa ecdSa)
        {
            if (ecdSa == null)
            {
                throw new ArgumentNullException("ecdSa");
            }

            System.Security.Cryptography.ECParameters ecParameters = ecdSa.ExportParameters(true);
            var webKey = new Track2Sdk.JsonWebKey(ecdSa)
            {
                // note: Keyvault need distinguish EC and EC-HSM
                KeyType   = Track2Sdk.KeyType.EcHsm,
                CurveName = ecParameters.Curve.CurveType.ToString(),
                D         = ecParameters.D,
                X         = ecParameters.Q.X,
                Y         = ecParameters.Q.Y
            };

            return(webKey);
        }
Esempio n. 4
0
        public static ECDiffieHellmanCngPublicKey FromXmlString(string xml)
        {
            if (xml == null)
            {
                throw new ArgumentNullException("xml");
            }

            bool         isEcdh;
            ECParameters parameters = Rfc4050KeyFormatter.FromXml(xml, out isEcdh);

            if (!isEcdh)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHRequiresECDHKey), "xml");
            }

            CngKeyBlobFormat format;
            string           curveName;

            byte[] blob = ECCng.EcdhParametersToBlob(ref parameters, out format, out curveName);
            return(new ECDiffieHellmanCngPublicKey(blob, curveName, format));
        }
Esempio n. 5
0
        public override unsafe bool TryExportPkcs8PrivateKey(
            Span <byte> destination,
            out int bytesWritten)
        {
            ECParameters ecParameters = ExportParameters(true);

            fixed(byte *privPtr = ecParameters.D)
            {
                try
                {
                    using (AsnWriter writer = EccKeyFormatHelper.WritePkcs8PrivateKey(ecParameters))
                    {
                        return(writer.TryEncode(destination, out bytesWritten));
                    }
                }
                finally
                {
                    CryptographicOperations.ZeroMemory(ecParameters.D);
                }
            }
        }
Esempio n. 6
0
        internal static void ExportNamedCurveParameters(ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters)
        {
            // We now have a buffer laid out as follows:
            //     BCRYPT_ECCKEY_BLOB   header
            //     byte[cbKey]          Q.X
            //     byte[cbKey]          Q.Y
            //     -- Private only --
            //     byte[cbKey]          D

            KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(ecBlob, 0);

            // Check the magic value in the key blob header. If the blob does not have the required magic,
            // then throw a CryptographicException.
            CheckMagicValueOfKey(magic, includePrivateParameters);

            unsafe
            {
                // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header.
                if (ecBlob.Length < sizeof(BCRYPT_ECCKEY_BLOB))
                    throw ErrorCode.E_FAIL.ToCryptographicException();

                fixed(byte *pEcBlob = &ecBlob[0])
                {
                    BCRYPT_ECCKEY_BLOB *pBcryptBlob = (BCRYPT_ECCKEY_BLOB *)pEcBlob;

                    int offset = sizeof(BCRYPT_ECCKEY_BLOB);

                    ecParams.Q = new ECPoint
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey)
                    };

                    if (includePrivateParameters)
                    {
                        ecParams.D = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey);
                    }
                }
            }
        }
        /// <summary>
        ///  Exports the key used by the ECC object into an <see cref="ECParameters"/> object.
        ///  If the key was created as a named curve, the Curve property will contain named curve parameters
        ///  otherwise it will contain explicit parameters.
        /// </summary>
        /// <exception cref="CryptographicException">
        ///  if there was an issue obtaining the curve values.
        /// </exception>
        /// <returns>The key and named curve parameters used by the ECC object.</returns>
        public override ECParameters ExportParameters()
        {
            using (CngKey key = Import())
            {
                ECParameters ecparams  = default;
                string?      curveName = key.GetCurveName(out _);

                if (string.IsNullOrEmpty(curveName))
                {
                    byte[] fullKeyBlob = ECCng.ExportFullKeyBlob(key, includePrivateParameters: false);
                    ECCng.ExportPrimeCurveParameters(ref ecparams, fullKeyBlob, includePrivateParameters: false);
                }
                else
                {
                    byte[] keyBlob = ECCng.ExportKeyBlob(key, includePrivateParameters: false);
                    ECCng.ExportNamedCurveParameters(ref ecparams, keyBlob, includePrivateParameters: false);
                    ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName);
                }

                return(ecparams);
            }
        }
Esempio n. 8
0
        internal const string ECDSA_P521_OID_VALUE = "1.3.132.0.35";        // Also called nistP521or secP521r1

        public int ImportParameters(ECParameters parameters)
        {
            SafeEcKeyHandle key;

            parameters.Validate();

            if (parameters.Curve.IsPrime)
            {
                key = ImportPrimeCurveParameters(parameters);
            }
            else if (parameters.Curve.IsCharacteristic2)
            {
                key = ImportCharacteristic2CurveParameters(parameters);
            }
            else if (parameters.Curve.IsNamed)
            {
                key = ImportNamedCurveParameters(parameters);
            }
            else
            {
                throw new PlatformNotSupportedException(
                          SR.Format(SR.Cryptography_CurveNotSupported, parameters.Curve.CurveType.ToString()));
            }

            if (key == null || key.IsInvalid)
            {
                Exception e = Interop.Crypto.CreateOpenSslCryptographicException();
                key?.Dispose();
                throw e;
            }

            // The Import* methods above may have polluted the error queue even if in the end they succeeded.
            // Clean up the error queue.
            Interop.Crypto.ErrClearError();

            FreeKey();
            _key = new Lazy <SafeEcKeyHandle>(key);
            return(KeySize);
        }
Esempio n. 9
0
        private static SafeSecKeyRefHandle ImportKey(ECParameters parameters)
        {
            bool isPrivateKey = parameters.D != null;

            byte[] blob;

            if (isPrivateKey)
            {
                using (AsnWriter privateKey = EccKeyFormatHelper.WriteECPrivateKey(parameters))
                {
                    blob = privateKey.Encode();
                }
            }
            else
            {
                using (AsnWriter publicKey = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters))
                {
                    blob = publicKey.Encode();
                }
            }

            return(Interop.AppleCrypto.ImportEphemeralKey(blob, isPrivateKey));
        }
Esempio n. 10
0
        public override unsafe bool TryExportEncryptedPkcs8PrivateKey(
            ReadOnlySpan <char> password,
            PbeParameters pbeParameters,
            Span <byte> destination,
            out int bytesWritten)
        {
            if (pbeParameters == null)
            {
                throw new ArgumentNullException(nameof(pbeParameters));
            }

            PasswordBasedEncryption.ValidatePbeParameters(
                pbeParameters,
                password,
                ReadOnlySpan <byte> .Empty);

            ECParameters ecParameters = ExportParameters(true);

            fixed(byte *privPtr = ecParameters.D)
            {
                try
                {
                    AsnWriter pkcs8PrivateKey = EccKeyFormatHelper.WritePkcs8PrivateKey(ecParameters);

                    AsnWriter writer = KeyFormatHelper.WriteEncryptedPkcs8(
                        password,
                        pkcs8PrivateKey,
                        pbeParameters);

                    return(writer.TryEncode(destination, out bytesWritten));
                }
                finally
                {
                    CryptographicOperations.ZeroMemory(ecParameters.D);
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        ///     Get a handle to the secret agreement generated between two parties
        /// </summary>
        public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException(nameof(otherPartyPublicKey));
            }

            if (otherPartyPublicKey is ECDiffieHellmanCngPublicKey otherKey)
            {
                using (CngKey importedKey = otherKey.Import())
                {
                    return(DeriveSecretAgreementHandle(importedKey));
                }
            }

            ECParameters otherPartyParameters = otherPartyPublicKey.ExportParameters();

            using (ECDiffieHellmanCng otherPartyCng = (ECDiffieHellmanCng)Create(otherPartyParameters))
                using (otherKey = (ECDiffieHellmanCngPublicKey)otherPartyCng.PublicKey)
                    using (CngKey importedKey = otherKey.Import())
                    {
                        return(DeriveSecretAgreementHandle(importedKey));
                    }
        }
Esempio n. 12
0
            public override void ImportParameters(ECParameters parameters)
            {
                parameters.Validate();

                bool isPrivateKey = parameters.D != null;

                if (isPrivateKey)
                {
                    // Start with the private key, in case some of the private key fields don't
                    // match the public key fields and the system determines an integrity failure.
                    //
                    // Public import should go off without a hitch.
                    SafeSecKeyRefHandle privateKey = ImportKey(parameters);

                    ECParameters publicOnly = parameters;
                    publicOnly.D = null;

                    SafeSecKeyRefHandle publicKey;
                    try
                    {
                        publicKey = ImportKey(publicOnly);
                    }
                    catch
                    {
                        privateKey.Dispose();
                        throw;
                    }

                    SetKey(SecKeyPair.PublicPrivatePair(publicKey, privateKey));
                }
                else
                {
                    SafeSecKeyRefHandle publicKey = ImportKey(parameters);
                    SetKey(SecKeyPair.PublicOnly(publicKey));
                }
            }
        private static SafeSecKeyRefHandle ImportKey(ECParameters parameters)
        {
            AsnWriter keyWriter;
            bool      hasPrivateKey;

            if (parameters.D != null)
            {
                keyWriter     = EccKeyFormatHelper.WriteECPrivateKey(parameters);
                hasPrivateKey = true;
            }
            else
            {
                keyWriter     = EccKeyFormatHelper.WriteSubjectPublicKeyInfo(parameters);
                hasPrivateKey = false;
            }

            byte[] rented = CryptoPool.Rent(keyWriter.GetEncodedLength());

            if (!keyWriter.TryEncode(rented, out int written))
            {
                Debug.Fail("TryEncode failed with a pre-allocated buffer");
                throw new InvalidOperationException();
            }

            // Explicitly clear the inner buffer
            keyWriter.Reset();

            try
            {
                return(Interop.AppleCrypto.ImportEphemeralKey(rented.AsSpan(0, written), hasPrivateKey));
            }
            finally
            {
                CryptoPool.Return(rented, written);
            }
        }
Esempio n. 14
0
        private static SafeSecKeyRefHandle ImportLegacyPrivateKey(ref ECParameters parameters)
        {
            AsnWriter keyWriter = EccKeyFormatHelper.WriteECPrivateKey(parameters);

            byte[] rented = CryptoPool.Rent(keyWriter.GetEncodedLength());

            if (!keyWriter.TryEncode(rented, out int written))
            {
                Debug.Fail("TryEncode failed with a pre-allocated buffer");
                throw new InvalidOperationException();
            }

            // Explicitly clear the inner buffer
            keyWriter.Reset();

            try
            {
                return(Interop.AppleCrypto.ImportEphemeralKey(rented.AsSpan(0, written), true));
            }
            finally
            {
                CryptoPool.Return(rented, written);
            }
        }
 public ECDiffieHellmanSecurityTransformsPublicKey(ECParameters ecParameters)
 {
     Debug.Assert(ecParameters.D == null);
     _ecc = new EccSecurityTransforms(nameof(ECDiffieHellmanPublicKey));
     _ecc.ImportParameters(ecParameters);
 }
Esempio n. 16
0
 public virtual void ImportParameters (ECParameters parameters)
 {
     throw new NotImplementedException ();
 }
Esempio n. 17
0
 public override void ImportParameters(ECParameters parameters)
 {
     KeySizeValue = _ecc.ImportParameters(parameters);
 }
Esempio n. 18
0
 /// <summary>
 /// When overridden in a derived class, imports the specified ECParameters.
 /// </summary>
 /// <param name="parameters">The curve parameters.</param>
 public virtual void ImportParameters(ECParameters parameters)
 {
     throw DerivedClassMustOverride();
 }
Esempio n. 19
0
        internal static void ReadPkcs8Blob(this DerSequenceReader reader, ref ECParameters parameters)
        {
            // OneAsymmetricKey ::= SEQUENCE {
            //   version                   Version,
            //   privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
            //   privateKey                PrivateKey,
            //   attributes            [0] Attributes OPTIONAL,
            //   ...,
            //   [[2: publicKey        [1] PublicKey OPTIONAL ]],
            //   ...
            // }
            //
            // PrivateKeyInfo ::= OneAsymmetricKey
            //
            // PrivateKey ::= OCTET STRING

            int version = reader.ReadInteger();

            // We understand both version 0 and 1 formats,
            // which are now known as v1 and v2, respectively.
            if (version > 1)
            {
                throw new CryptographicException();
            }

            {
                // Ensure we're reading EC Public Key (well, Private, but the OID says Public)
                DerSequenceReader algorithm = reader.ReadSequence();

                string algorithmOid = algorithm.ReadOidAsString();

                if (algorithmOid != s_idEcPublicKey.Value)
                {
                    throw new CryptographicException();
                }
            }

            byte[] privateKeyBlob = reader.ReadOctetString();

            try
            {
                // ECPrivateKey{CURVES:IOSet} ::= SEQUENCE {
                //   version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
                //   privateKey OCTET STRING,
                //   parameters [0] Parameters{{IOSet}} OPTIONAL,
                //   publicKey  [1] BIT STRING OPTIONAL
                // }
                DerSequenceReader keyReader = new DerSequenceReader(privateKeyBlob);
                version = keyReader.ReadInteger();

                // We understand the version 1 format
                if (version > 1)
                {
                    throw new CryptographicException();
                }

                parameters.D = keyReader.ReadOctetString();

                // Check for context specific 0
                const byte ConstructedContextSpecific =
                    DerSequenceReader.ContextSpecificTagFlag | DerSequenceReader.ConstructedFlag;

                const byte ConstructedContextSpecific0 = (ConstructedContextSpecific | 0);
                const byte ConstructedContextSpecific1 = (ConstructedContextSpecific | 1);

                if (keyReader.PeekTag() != ConstructedContextSpecific0)
                {
                    throw new CryptographicException();
                }

                // Parameters ::= CHOICE {
                //   ecParameters ECParameters,
                //   namedCurve CURVES.&id({ CurveNames}),
                //   implicitlyCA  NULL
                // }
                DerSequenceReader parametersReader = keyReader.ReadSequence();

                if (parametersReader.PeekTag() != (int)DerSequenceReader.DerTag.ObjectIdentifier)
                {
                    throw new PlatformNotSupportedException(SR.Cryptography_ECC_NamedCurvesOnly);
                }

                parameters.Curve = ECCurve.CreateFromValue(parametersReader.ReadOidAsString());

                // Check for context specific 1
                if (keyReader.PeekTag() != ConstructedContextSpecific1)
                {
                    throw new CryptographicException();
                }

                keyReader = keyReader.ReadSequence();
                byte[] encodedPoint = keyReader.ReadBitString();
                ReadEncodedPoint(encodedPoint, ref parameters);

                // We don't care about the rest of the blob here, but it's expected to not exist.
            }
            finally
            {
                Array.Clear(privateKeyBlob, 0, privateKeyBlob.Length);
            }
        }
 internal ECDiffieHellmanOpenSslPublicKey(ECParameters parameters)
 {
     _key = new ECOpenSsl(parameters);
 }
Esempio n. 21
0
 internal bool TryExportDataKeyParameters(bool includePrivateParameters, ref ECParameters ecParameters)
 {
     return(_ecc.TryExportDataKeyParameters(includePrivateParameters, KeySize, ref ecParameters));
 }
        internal static ECParameters GetECKeyParameters(
            SafeEcKeyHandle key,
            bool includePrivate)
        {
            SafeBignumHandle qx_bn, qy_bn, d_bn;
            IntPtr d_bn_not_owned;
            int qx_cb, qy_cb, d_cb;
            ECParameters parameters = new ECParameters();

            bool refAdded = false;
            try
            {
                key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned
                if (!CryptoNative_GetECKeyParameters(
                    key,
                    includePrivate,
                    out qx_bn, out qx_cb,
                    out qy_bn, out qy_cb,
                    out d_bn_not_owned, out d_cb))
                {
                    throw Interop.Crypto.CreateOpenSslCryptographicException();
                }

                using (qx_bn)
                using (qy_bn)
                using (d_bn = new SafeBignumHandle(d_bn_not_owned, false))
                {
                    // Match Windows semantics where qx, qy, and d have same length
                    int cbKey = GetMax(qx_cb, qy_cb, d_cb);

                    parameters.Q = new ECPoint
                    {
                        X = Crypto.ExtractBignum(qx_bn, cbKey),
                        Y = Crypto.ExtractBignum(qy_bn, cbKey)
                    };
                    parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_bn, cbKey);
                }
            }
            finally
            {
                if (refAdded)
                    key.DangerousRelease();
            }

            return parameters;
        }
Esempio n. 23
0
        internal static void ExportPrimeCurveParameters(ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters)
        {
            // We now have a buffer laid out as follows:
            //     BCRYPT_ECCFULLKEY_BLOB       header
            //     byte[cbFieldLength]          P
            //     byte[cbFieldLength]          A
            //     byte[cbFieldLength]          B
            //     byte[cbFieldLength]          G.X
            //     byte[cbFieldLength]          G.Y
            //     byte[cbSubgroupOrder]        Order (n)
            //     byte[cbCofactor]             Cofactor (h)
            //     byte[cbSeed]                 Seed
            //     byte[cbFieldLength]          Q.X
            //     byte[cbFieldLength]          Q.Y
            //     -- Private only --
            //     byte[cbSubgroupOrder]        D

            KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(ecBlob, 0);

            // Check the magic value in the key blob header. If the blob does not have the required magic,
            // then throw a CryptographicException.
            CheckMagicValueOfKey(magic, includePrivateParameters);

            unsafe
            {
                // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header.
                if (ecBlob.Length < sizeof(BCRYPT_ECCFULLKEY_BLOB))
                    throw ErrorCode.E_FAIL.ToCryptographicException();

                fixed (byte* pEcBlob = ecBlob)
                {
                    BCRYPT_ECCFULLKEY_BLOB* pBcryptBlob = (BCRYPT_ECCFULLKEY_BLOB*)pEcBlob;

                    var primeCurve = new ECCurve();
                    primeCurve.CurveType = ConvertToCurveTypeEnum(pBcryptBlob->CurveType);
                    primeCurve.Hash = GetHashAlgorithmName(pBcryptBlob->CurveGenerationAlgId);

                    int offset = sizeof(BCRYPT_ECCFULLKEY_BLOB);

                    primeCurve.Prime = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.A = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.B = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.G = new ECPoint()
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                    };
                    primeCurve.Order = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder);
                    primeCurve.Cofactor = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbCofactor);

                    // Optional parameters
                    primeCurve.Seed = pBcryptBlob->cbSeed == 0 ? null : Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSeed);

                    ecParams.Q = new ECPoint
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength)
                    };

                    if (includePrivateParameters)
                    {
                        ecParams.D = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder);
                    }

                    ecParams.Curve = primeCurve;
                }
            }
        }
Esempio n. 24
0
        internal static void ExportNamedCurveParameters(ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters)
        {
            // We now have a buffer laid out as follows:
            //     BCRYPT_ECCKEY_BLOB   header
            //     byte[cbKey]          Q.X
            //     byte[cbKey]          Q.Y
            //     -- Private only --
            //     byte[cbKey]          D

            KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(ecBlob, 0);

            // Check the magic value in the key blob header. If the blob does not have the required magic,
            // then throw a CryptographicException.
            CheckMagicValueOfKey(magic, includePrivateParameters);

            unsafe
            {
                // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header.
                if (ecBlob.Length < sizeof(BCRYPT_ECCKEY_BLOB))
                    throw ErrorCode.E_FAIL.ToCryptographicException();

                fixed (byte* pEcBlob = ecBlob)
                {
                    BCRYPT_ECCKEY_BLOB* pBcryptBlob = (BCRYPT_ECCKEY_BLOB*)pEcBlob;

                    int offset = sizeof(BCRYPT_ECCKEY_BLOB);

                    ecParams.Q = new ECPoint
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey)
                    };

                    if (includePrivateParameters)
                    {
                        ecParams.D = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey);
                    }
                }
            }
        }
Esempio n. 25
0
 /// <summary>
 /// When overridden in a derived class, imports the specified ECParameters.
 /// </summary>
 /// <param name="parameters">The curve parameters.</param>
 public virtual void ImportParameters(ECParameters parameters)
 {
     throw new NotSupportedException(SR.NotSupported_SubclassOverride);
 }
Esempio n. 26
0
 /// <summary>
 /// Creates an instance of the platform specific implementation of the cref="ECDsa" algorithm.
 /// </summary>
 /// <param name="parameters">
 /// The <see cref="ECParameters"/> representing the elliptic curve parameters.
 /// </param>
 public static ECDsa Create(ECParameters parameters)
 {
     ECDsa ec = new ECDsaImplementation.ECDsaCng();
     ec.ImportParameters(parameters);
     return ec;
 }
Esempio n. 27
0
        internal static byte[] GetPrimeCurveBlob(ref ECParameters parameters)
        {
            Debug.Assert(parameters.Curve.IsPrime);

            bool includePrivateParameters = (parameters.D != null);
            ECCurve curve = parameters.Curve;
            byte[] blob;
            unsafe
            {
                // We need to build a key blob structured as follows:
                //     BCRYPT_ECCFULLKEY_BLOB       header
                //     byte[cbFieldLength]          P
                //     byte[cbFieldLength]          A
                //     byte[cbFieldLength]          B
                //     byte[cbFieldLength]          G.X
                //     byte[cbFieldLength]          G.Y
                //     byte[cbSubgroupOrder]        Order (n)
                //     byte[cbCofactor]             Cofactor (h)
                //     byte[cbSeed]                 Seed
                //     byte[cbFieldLength]          Q.X
                //     byte[cbFieldLength]          Q.Y
                //     -- Only if "includePrivateParameters" is true --
                //     byte[cbSubgroupOrder]        D

                int blobSize = sizeof(BCRYPT_ECCFULLKEY_BLOB) +
                    curve.Prime.Length +
                    curve.A.Length +
                    curve.B.Length +
                    curve.G.X.Length +
                    curve.G.Y.Length +
                    curve.Order.Length +
                    curve.Cofactor.Length +
                    (curve.Seed == null ? 0 : curve.Seed.Length) +
                    parameters.Q.X.Length +
                    parameters.Q.Y.Length;

                if (includePrivateParameters)
                {
                    blobSize += parameters.D.Length;
                }

                blob = new byte[blobSize];
                fixed (byte* pBlob = blob)
                {
                    // Build the header
                    BCRYPT_ECCFULLKEY_BLOB* pBcryptBlob = (BCRYPT_ECCFULLKEY_BLOB*)pBlob;
                    pBcryptBlob->Version = 1; // No constant for this found in bcrypt.h
                    pBcryptBlob->Magic = includePrivateParameters ?
                        KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC :
                        KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC;
                    pBcryptBlob->cbCofactor = curve.Cofactor.Length;
                    pBcryptBlob->cbFieldLength = parameters.Q.X.Length;
                    pBcryptBlob->cbSeed = curve.Seed == null ? 0 : curve.Seed.Length;
                    pBcryptBlob->cbSubgroupOrder = curve.Order.Length;
                    pBcryptBlob->CurveGenerationAlgId = GetHashAlgorithmId(curve.Hash);
                    pBcryptBlob->CurveType = ConvertToCurveTypeEnum(curve.CurveType);

                    // Emit the blob
                    int offset = sizeof(BCRYPT_ECCFULLKEY_BLOB);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Prime);
                    Interop.BCrypt.Emit(blob, ref offset, curve.A);
                    Interop.BCrypt.Emit(blob, ref offset, curve.B);
                    Interop.BCrypt.Emit(blob, ref offset, curve.G.X);
                    Interop.BCrypt.Emit(blob, ref offset, curve.G.Y);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Order);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Cofactor);
                    if (curve.Seed != null)
                    {
                        Interop.BCrypt.Emit(blob, ref offset, curve.Seed);
                    }
                    Interop.BCrypt.Emit(blob, ref offset, parameters.Q.X);
                    Interop.BCrypt.Emit(blob, ref offset, parameters.Q.Y);
                    if (includePrivateParameters)
                    {
                        Interop.BCrypt.Emit(blob, ref offset, parameters.D);
                    }

                    // We better have computed the right allocation size above!
                    Debug.Assert(offset == blobSize, "offset == blobSize");
                }

                return blob;
            }
        }
Esempio n. 28
0
 private static void ExtractPublicKeyFromPrivateKey(ref ECParameters ecParameters)
     => throw new PlatformNotSupportedException(SR.Cryptography_NotValidPublicOrPrivateKey);
Esempio n. 29
0
 public static partial ECDiffieHellman Create(ECParameters parameters);
Esempio n. 30
0
 public static partial ECDsa Create(ECParameters parameters);
Esempio n. 31
0
 public ECAndroid(ECParameters ecParameters)
 {
     ImportParameters(ecParameters);
 }
Esempio n. 32
0
 public override void ImportParameters(ECParameters parameters)
 {
     ThrowIfDisposed();
     KeySizeValue = _key.ImportParameters(parameters);
 }
Esempio n. 33
0
        internal static void ReadSubjectPublicKeyInfo(this DerSequenceReader keyInfo, ref ECParameters parameters)
        {
            // SubjectPublicKeyInfo::= SEQUENCE  {
            //    algorithm AlgorithmIdentifier,
            //    subjectPublicKey     BIT STRING  }
            DerSequenceReader algorithm    = keyInfo.ReadSequence();
            string            algorithmOid = algorithm.ReadOidAsString();

            // EC Public Key
            if (algorithmOid != s_idEcPublicKey.Value)
            {
                throw new CryptographicException();
            }

            if (algorithm.PeekTag() != (int)DerSequenceReader.DerTag.ObjectIdentifier)
            {
                throw new PlatformNotSupportedException(SR.Cryptography_ECC_NamedCurvesOnly);
            }

            parameters.Curve = ECCurve.CreateFromValue(algorithm.ReadOidAsString());

            byte[] encodedPoint = keyInfo.ReadBitString();
            ReadEncodedPoint(encodedPoint, ref parameters);

            // We don't care about the rest of the blob here, but it's expected to not exist.
        }
Esempio n. 34
0
 public override void ImportParameters(ECParameters parameters)
 {
     throw new NotImplementedException();
 }
        internal static ECParameters GetECCurveParameters(
            SafeEcKeyHandle key,
            bool includePrivate)
        {
            ECCurve.ECCurveType curveType;
            SafeBignumHandle qx_bn, qy_bn, p_bn, a_bn, b_bn, gx_bn, gy_bn, order_bn, cofactor_bn, seed_bn;
            IntPtr d_bn_not_owned;
            int qx_cb, qy_cb, p_cb, a_cb, b_cb, gx_cb, gy_cb, order_cb, cofactor_cb, seed_cb, d_cb;

            bool refAdded = false;
            try
            {
                key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned
                if (!CryptoNative_GetECCurveParameters(
                    key,
                    includePrivate,
                    out curveType,
                    out qx_bn, out qx_cb,
                    out qy_bn, out qy_cb,
                    out d_bn_not_owned, out d_cb,
                    out p_bn, out p_cb,
                    out a_bn, out a_cb,
                    out b_bn, out b_cb,
                    out gx_bn, out gx_cb,
                    out gy_bn, out gy_cb,
                    out order_bn, out order_cb,
                    out cofactor_bn, out cofactor_cb,
                    out seed_bn, out seed_cb))
                {
                    throw Interop.Crypto.CreateOpenSslCryptographicException();
                }

                using (qx_bn)
                using (qy_bn)
                using (p_bn)
                using (a_bn)
                using (b_bn)
                using (gx_bn)
                using (gy_bn)
                using (order_bn)
                using (cofactor_bn)
                using (seed_bn)
                using (var d_h = new SafeBignumHandle(d_bn_not_owned, false))
                {
                    int cbFieldLength;
                    int pFieldLength;
                    if (curveType == ECCurve.ECCurveType.Characteristic2)
                    {
                        // Match Windows semantics where a,b,gx,gy,qx,qy have same length
                        // Treat length of m separately as it is not tied to other fields for Char2 (Char2 not supported by Windows) 
                        cbFieldLength = GetMax(new[] { a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb });
                        pFieldLength = p_cb;
                    }
                    else
                    {
                        // Match Windows semantics where p,a,b,gx,gy,qx,qy have same length
                        cbFieldLength = GetMax(new[] { p_cb, a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb });
                        pFieldLength = cbFieldLength;
                    }

                    // Match Windows semantics where order and d have same length
                    int cbSubgroupOrder = GetMax(order_cb, d_cb);

                    // Copy values to ECParameters
                    ECParameters parameters = new ECParameters();
                    parameters.Q = new ECPoint
                    {
                        X = Crypto.ExtractBignum(qx_bn, cbFieldLength),
                        Y = Crypto.ExtractBignum(qy_bn, cbFieldLength)
                    };
                    parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_h, cbSubgroupOrder);

                    var curve = parameters.Curve;
                    curve.CurveType = curveType;
                    curve.A = Crypto.ExtractBignum(a_bn, cbFieldLength);
                    curve.B = Crypto.ExtractBignum(b_bn, cbFieldLength);
                    curve.G = new ECPoint
                    {
                        X = Crypto.ExtractBignum(gx_bn, cbFieldLength),
                        Y = Crypto.ExtractBignum(gy_bn, cbFieldLength)
                    };
                    curve.Order = Crypto.ExtractBignum(order_bn, cbSubgroupOrder);

                    if (curveType == ECCurve.ECCurveType.Characteristic2)
                    {
                        curve.Polynomial = Crypto.ExtractBignum(p_bn, pFieldLength);
                    }
                    else
                    {
                        curve.Prime = Crypto.ExtractBignum(p_bn, pFieldLength);
                    }

                    // Optional parameters
                    curve.Cofactor = cofactor_cb == 0 ? null : Crypto.ExtractBignum(cofactor_bn, cofactor_cb);
                    curve.Seed = seed_cb == 0 ? null : Crypto.ExtractBignum(seed_bn, seed_cb);

                    parameters.Curve = curve;
                    return parameters;
                }
            }
            finally
            {
                if (refAdded)
                    key.DangerousRelease();
            }
        }
            private static SafeEcKeyHandle ImportCharacteristic2CurveParameters(ECParameters parameters)
            {
                Debug.Assert(parameters.Curve.IsCharacteristic2);
                SafeEcKeyHandle key = Interop.Crypto.EcKeyCreateByExplicitParameters(
                    parameters.Curve.CurveType,
                    parameters.Q.X, parameters.Q.X.Length,
                    parameters.Q.Y, parameters.Q.Y.Length,
                    parameters.D, parameters.D == null ? 0 : parameters.D.Length,
                    parameters.Curve.Polynomial, parameters.Curve.Polynomial.Length,
                    parameters.Curve.A, parameters.Curve.A.Length,
                    parameters.Curve.B, parameters.Curve.B.Length,
                    parameters.Curve.G.X, parameters.Curve.G.X.Length,
                    parameters.Curve.G.Y, parameters.Curve.G.Y.Length,
                    parameters.Curve.Order, parameters.Curve.Order.Length,
                    parameters.Curve.Cofactor, parameters.Curve.Cofactor.Length,
                    parameters.Curve.Seed, parameters.Curve.Seed == null ? 0 : parameters.Curve.Seed.Length);

                return key;
            }
Esempio n. 37
0
 public override void ImportParameters(ECParameters parameters)
 {
     ThrowIfDisposed();
     _key.ImportParameters(parameters);
     ForceSetKeySize(_key.KeySize);
 }
Esempio n. 38
0
 public static ECDsa Create (ECParameters parameters)
 {
     throw new NotImplementedException ();
 }
        private static ECDsa DecodeECDsaPublicKey(CertificatePal certificatePal)
        {
            ECDsa ecdsa;
            using (SafeBCryptKeyHandle bCryptKeyHandle = ImportPublicKeyInfo(certificatePal.CertContext))
            {
                CngKeyBlobFormat blobFormat;
                byte[] keyBlob;
#if NETNATIVE
                blobFormat = CngKeyBlobFormat.EccPublicBlob;
                keyBlob = ExportKeyBlob(bCryptKeyHandle, blobFormat);
                using (CngKey cngKey = CngKey.Import(keyBlob, blobFormat))
                {
                    ecdsa = new ECDsaCng(cngKey);
                }
#else
                string curveName = GetCurveName(bCryptKeyHandle);

                if (curveName == null)
                {
                    if (HasExplicitParameters(bCryptKeyHandle))
                    {
                        blobFormat = CngKeyBlobFormat.EccFullPublicBlob;
                    }
                    else
                    {
                        blobFormat = CngKeyBlobFormat.EccPublicBlob;
                    }

                    keyBlob = ExportKeyBlob(bCryptKeyHandle, blobFormat);
                    using (CngKey cngKey = CngKey.Import(keyBlob, blobFormat))
                    {
                        ecdsa = new ECDsaCng(cngKey);
                    }
                }
                else
                {
                    blobFormat = CngKeyBlobFormat.EccPublicBlob;
                    keyBlob = ExportKeyBlob(bCryptKeyHandle, blobFormat);
                    ECParameters ecparams = new ECParameters();
                    ExportNamedCurveParameters(ref ecparams, keyBlob, false);
                    ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName);
                    ecdsa = new ECDsaCng();
                    ecdsa.ImportParameters(ecparams);
                }
#endif
            }

            return ecdsa;
        }
            private static SafeEcKeyHandle ImportNamedCurveParameters(ECParameters parameters)
            {
                Debug.Assert(parameters.Curve.IsNamed);

                // Use oid Value first if present, otherwise FriendlyName
                string oid = !string.IsNullOrEmpty(parameters.Curve.Oid.Value) ?
                    parameters.Curve.Oid.Value : parameters.Curve.Oid.FriendlyName;

                SafeEcKeyHandle key = Interop.Crypto.EcKeyCreateByKeyParameters(
                    oid,
                    parameters.Q.X, parameters.Q.X.Length,
                    parameters.Q.Y, parameters.Q.Y.Length,
                    parameters.D, parameters.D == null ? 0 : parameters.D.Length);

                return key;
            }
Esempio n. 41
0
 internal ECDiffieHellmanAndroidPublicKey(ECParameters parameters)
 {
     _key = new ECAndroid(parameters);
 }
Esempio n. 42
0
        internal static void ExportPrimeCurveParameters(ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters)
        {
            // We now have a buffer laid out as follows:
            //     BCRYPT_ECCFULLKEY_BLOB       header
            //     byte[cbFieldLength]          P
            //     byte[cbFieldLength]          A
            //     byte[cbFieldLength]          B
            //     byte[cbFieldLength]          G.X
            //     byte[cbFieldLength]          G.Y
            //     byte[cbSubgroupOrder]        Order (n)
            //     byte[cbCofactor]             Cofactor (h)
            //     byte[cbSeed]                 Seed
            //     byte[cbFieldLength]          Q.X
            //     byte[cbFieldLength]          Q.Y
            //     -- Private only --
            //     byte[cbSubgroupOrder]        D

            KeyBlobMagicNumber magic = (KeyBlobMagicNumber)BitConverter.ToInt32(ecBlob, 0);

            // Check the magic value in the key blob header. If the blob does not have the required magic,
            // then throw a CryptographicException.
            CheckMagicValueOfKey(magic, includePrivateParameters);

            unsafe
            {
                // Fail-fast if a rogue provider gave us a blob that isn't even the size of the blob header.
                if (ecBlob.Length < sizeof(BCRYPT_ECCFULLKEY_BLOB))
                    throw ErrorCode.E_FAIL.ToCryptographicException();

                fixed(byte *pEcBlob = &ecBlob[0])
                {
                    BCRYPT_ECCFULLKEY_BLOB *pBcryptBlob = (BCRYPT_ECCFULLKEY_BLOB *)pEcBlob;

                    var primeCurve = new ECCurve();

                    primeCurve.CurveType = ConvertToCurveTypeEnum(pBcryptBlob->CurveType);
                    primeCurve.Hash      = GetHashAlgorithmName(pBcryptBlob->CurveGenerationAlgId);

                    int offset = sizeof(BCRYPT_ECCFULLKEY_BLOB);

                    primeCurve.Prime = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.A     = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.B     = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength);
                    primeCurve.G     = new ECPoint()
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                    };
                    primeCurve.Order    = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder);
                    primeCurve.Cofactor = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbCofactor);

                    // Optional parameters
                    primeCurve.Seed = pBcryptBlob->cbSeed == 0 ? null : Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSeed);

                    ecParams.Q = new ECPoint
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbFieldLength)
                    };

                    if (includePrivateParameters)
                    {
                        ecParams.D = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbSubgroupOrder);
                    }

                    ecParams.Curve = primeCurve;
                }
            }
        }
Esempio n. 43
0
        /// <summary>
        /// Get the secret agreement generated between two parties
        /// </summary>
        private byte[]? DeriveSecretAgreement(ECDiffieHellmanPublicKey otherPartyPublicKey, IncrementalHash?hasher)
        {
            Debug.Assert(otherPartyPublicKey != null);

            // Ensure that this ECDH object contains a private key by attempting a parameter export
            // which will throw an OpenSslCryptoException if no private key is available
            ECParameters thisKeyExplicit             = ExportExplicitParameters(true);
            bool         thisIsNamed                 = Interop.Crypto.EcKeyHasCurveName(_key.Value);
            ECDiffieHellmanOpenSslPublicKey?otherKey = otherPartyPublicKey as ECDiffieHellmanOpenSslPublicKey;
            bool disposeOtherKey = false;

            if (otherKey == null)
            {
                disposeOtherKey = true;

                ECParameters otherParameters =
                    thisIsNamed
                        ? otherPartyPublicKey.ExportParameters()
                        : otherPartyPublicKey.ExportExplicitParameters();

                otherKey = new ECDiffieHellmanOpenSslPublicKey(otherParameters);
            }

            bool otherIsNamed = otherKey.HasCurveName;

            SafeEvpPKeyHandle?ourKey   = null;
            SafeEvpPKeyHandle?theirKey = null;

            byte[]? rented = null;
            int secretLength = 0;

            try
            {
                if (otherKey.KeySize != KeySize)
                {
                    throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey));
                }

                if (otherIsNamed == thisIsNamed)
                {
                    ourKey   = _key.UpRefKeyHandle();
                    theirKey = otherKey.DuplicateKeyHandle();
                }
                else if (otherIsNamed)
                {
                    ourKey = _key.UpRefKeyHandle();

                    using (ECOpenSsl tmp = new ECOpenSsl(otherKey.ExportExplicitParameters()))
                    {
                        theirKey = tmp.UpRefKeyHandle();
                    }
                }
                else
                {
                    using (ECOpenSsl tmp = new ECOpenSsl(thisKeyExplicit))
                    {
                        ourKey = tmp.UpRefKeyHandle();
                    }

                    theirKey = otherKey.DuplicateKeyHandle();
                }

                using (SafeEvpPKeyCtxHandle ctx = Interop.Crypto.EvpPKeyCtxCreate(ourKey, theirKey, out uint secretLengthU))
                {
                    if (ctx == null || ctx.IsInvalid || secretLengthU == 0 || secretLengthU > int.MaxValue)
                    {
                        throw Interop.Crypto.CreateOpenSslCryptographicException();
                    }

                    secretLength = (int)secretLengthU;

                    // Indicate that secret can hold stackallocs from nested scopes
                    Span <byte> secret = stackalloc byte[0];

                    // Arbitrary limit. But it covers secp521r1, which is the biggest common case.
                    const int StackAllocMax = 66;

                    if (secretLength > StackAllocMax)
                    {
                        rented = CryptoPool.Rent(secretLength);
                        secret = new Span <byte>(rented, 0, secretLength);
                    }
                    else
                    {
                        secret = stackalloc byte[secretLength];
                    }

                    Interop.Crypto.EvpPKeyDeriveSecretAgreement(ctx, secret);

                    if (hasher == null)
                    {
                        return(secret.ToArray());
                    }
                    else
                    {
                        hasher.AppendData(secret);
                        return(null);
                    }
                }
            }
            finally
            {
                theirKey?.Dispose();
                ourKey?.Dispose();

                if (disposeOtherKey)
                {
                    otherKey.Dispose();
                }

                if (rented != null)
                {
                    CryptoPool.Return(rented, secretLength);
                }
            }
        }
Esempio n. 44
0
        internal static byte[] GetPrimeCurveBlob(ref ECParameters parameters, bool ecdh)
        {
            Debug.Assert(parameters.Curve.IsPrime);

            bool    includePrivateParameters = (parameters.D != null);
            ECCurve curve = parameters.Curve;

            byte[] blob;
            unsafe
            {
                // We need to build a key blob structured as follows:
                //     BCRYPT_ECCFULLKEY_BLOB       header
                //     byte[cbFieldLength]          P
                //     byte[cbFieldLength]          A
                //     byte[cbFieldLength]          B
                //     byte[cbFieldLength]          G.X
                //     byte[cbFieldLength]          G.Y
                //     byte[cbSubgroupOrder]        Order (n)
                //     byte[cbCofactor]             Cofactor (h)
                //     byte[cbSeed]                 Seed
                //     byte[cbFieldLength]          Q.X
                //     byte[cbFieldLength]          Q.Y
                //     -- Only if "includePrivateParameters" is true --
                //     byte[cbSubgroupOrder]        D

                int blobSize = sizeof(BCRYPT_ECCFULLKEY_BLOB) +
                               curve.Prime.Length +
                               curve.A.Length +
                               curve.B.Length +
                               curve.G.X.Length +
                               curve.G.Y.Length +
                               curve.Order.Length +
                               curve.Cofactor.Length +
                               (curve.Seed == null ? 0 : curve.Seed.Length) +
                               parameters.Q.X.Length +
                               parameters.Q.Y.Length;

                if (includePrivateParameters)
                {
                    blobSize += parameters.D.Length;
                }

                blob = new byte[blobSize];
                fixed(byte *pBlob = &blob[0])
                {
                    // Build the header
                    BCRYPT_ECCFULLKEY_BLOB *pBcryptBlob = (BCRYPT_ECCFULLKEY_BLOB *)pBlob;

                    pBcryptBlob->Version = 1; // No constant for this found in bcrypt.h
                    pBcryptBlob->Magic   = includePrivateParameters ?
                                           (ecdh ? KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC : KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC) :
                                           (ecdh ? KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC : KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC);
                    pBcryptBlob->cbCofactor           = curve.Cofactor.Length;
                    pBcryptBlob->cbFieldLength        = parameters.Q.X.Length;
                    pBcryptBlob->cbSeed               = curve.Seed == null ? 0 : curve.Seed.Length;
                    pBcryptBlob->cbSubgroupOrder      = curve.Order.Length;
                    pBcryptBlob->CurveGenerationAlgId = GetHashAlgorithmId(curve.Hash);
                    pBcryptBlob->CurveType            = ConvertToCurveTypeEnum(curve.CurveType);

                    // Emit the blob
                    int offset = sizeof(BCRYPT_ECCFULLKEY_BLOB);

                    Interop.BCrypt.Emit(blob, ref offset, curve.Prime);
                    Interop.BCrypt.Emit(blob, ref offset, curve.A);
                    Interop.BCrypt.Emit(blob, ref offset, curve.B);
                    Interop.BCrypt.Emit(blob, ref offset, curve.G.X);
                    Interop.BCrypt.Emit(blob, ref offset, curve.G.Y);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Order);
                    Interop.BCrypt.Emit(blob, ref offset, curve.Cofactor);
                    if (curve.Seed != null)
                    {
                        Interop.BCrypt.Emit(blob, ref offset, curve.Seed);
                    }
                    Interop.BCrypt.Emit(blob, ref offset, parameters.Q.X);
                    Interop.BCrypt.Emit(blob, ref offset, parameters.Q.Y);
                    if (includePrivateParameters)
                    {
                        Interop.BCrypt.Emit(blob, ref offset, parameters.D);
                    }

                    // We better have computed the right allocation size above!
                    Debug.Assert(offset == blobSize, "offset == blobSize");
                }

                return(blob);
            }
        }
Esempio n. 45
0
 /// <summary>
 /// When overridden in a derived class, imports the specified <see cref="ECParameters" />.
 /// </summary>
 /// <param name="parameters">The curve parameters.</param>
 /// <exception cref="NotSupportedException">
 /// A derived class has not provided an implementation.
 /// </exception>
 public virtual void ImportParameters(ECParameters parameters)
 {
     throw new NotSupportedException(SR.NotSupported_SubclassOverride);
 }
        private static void ExportNamedCurveParameters(ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters)
        {
            // We now have a buffer laid out as follows:
            //     BCRYPT_ECCKEY_BLOB   header
            //     byte[cbKey]          Q.X
            //     byte[cbKey]          Q.Y
            //     -- Private only --
            //     byte[cbKey]          D

            unsafe
            {
                Debug.Assert(ecBlob.Length >= sizeof(Interop.BCrypt.BCRYPT_ECCKEY_BLOB));

                fixed (byte* pEcBlob = ecBlob)
                {
                    Interop.BCrypt.BCRYPT_ECCKEY_BLOB* pBcryptBlob = (Interop.BCrypt.BCRYPT_ECCKEY_BLOB*)pEcBlob;

                    int offset = sizeof(Interop.BCrypt.BCRYPT_ECCKEY_BLOB);

                    ecParams.Q = new ECPoint
                    {
                        X = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey),
                        Y = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey)
                    };

                    if (includePrivateParameters)
                    {
                        ecParams.D = Interop.BCrypt.Consume(ecBlob, ref offset, pBcryptBlob->cbKey);
                    }
                }
            }
        }