public TpmPolicyNameHash(byte[] expectedNameHash, string branchName = "", string nodeId = null) : base(branchName, nodeId) { NameHash = Globs.CopyData(expectedNameHash); }
public byte[] Decrypt(byte[] data, byte[] iv = null) { byte[] paddedData; int unpadded = data.Length % BlockSize; paddedData = unpadded == 0 ? data : Globs.AddZeroToEnd(data, BlockSize - unpadded); #if TSS_USE_BCRYPT paddedData = Key.Decrypt(paddedData, null, iv ?? IV); return(Globs.CopyData(paddedData, 0, data.Length)); #else bool externalIV = iv != null && iv.Length > 0; if (externalIV) { Alg.IV = iv; } byte[] tempOut = null; if (Alg.Mode == CipherMode.ECB && Mode == CipherMode.CFB) { DecryptCFB(paddedData, Alg.IV, Alg.CreateEncryptor()); tempOut = unpadded == 0 ? paddedData : Globs.CopyData(paddedData, 0, data.Length); } else { ICryptoTransform dec = Alg.CreateDecryptor(); tempOut = new byte[data.Length]; using (var outStream = new MemoryStream(paddedData)) { var s = new CryptoStream(outStream, dec, CryptoStreamMode.Read); int numPlaintextBytes = s.Read(tempOut, 0, data.Length); Debug.Assert(numPlaintextBytes == data.Length); } } if (externalIV) { var src = data; var res = tempOut; if (res.Length > iv.Length) { src = Globs.CopyData(paddedData, src.Length / iv.Length, iv.Length); res = Globs.CopyData(tempOut, res.Length / iv.Length, iv.Length); } switch (Mode) { case CipherMode.CBC: case CipherMode.CFB: src.CopyTo(iv, 0); break; case CipherMode.OFB: XorEngine.Xor(res, src).CopyTo(iv, 0); break; case CipherMode.ECB: break; case CipherMode.CTS: Globs.Throw <ArgumentException>("Decrypt: Unsupported symmetric mode"); break; } } return(tempOut); #endif // !TSS_USE_BCRYPT }
private SymmCipher(CryptographicKey key, byte[] keyData, byte[] iv) { Key = key; KeyBuffer = keyData; IV = Globs.CopyData(iv) ?? new byte[BlockSize]; }
CreateSensitiveComposite(TpmPublic pub, ref byte[] keyData, out IPublicIdUnion publicId) { ISensitiveCompositeUnion newSens = null; publicId = null; if (pub.type == TpmAlgId.Rsa) { if (keyData != null) { newSens = new Tpm2bPrivateKeyRsa(keyData); publicId = pub.unique; } else { var newKeyPair = new RawRsa((pub.parameters as RsaParms).keyBits); // Put the key bits into the required structure envelopes newSens = new Tpm2bPrivateKeyRsa(newKeyPair.Private); publicId = new Tpm2bPublicKeyRsa(newKeyPair.Public); } } else if (pub.type == TpmAlgId.Symcipher) { var symDef = (SymDefObject)pub.parameters; if (symDef.Algorithm != TpmAlgId.Aes) { Globs.Throw <ArgumentException>("Unsupported symmetric algorithm"); return(null); } int keySize = (symDef.KeyBits + 7) / 8; if (keyData == null) { keyData = Globs.GetRandomBytes(keySize); } else if (keyData.Length != keySize) { keyData = Globs.CopyData(keyData); } else { Globs.Throw <ArgumentException>("Wrong symmetric key length"); return(null); } newSens = new Tpm2bSymKey(keyData); } else if (pub.type == TpmAlgId.Keyedhash) { var scheme = (pub.parameters as KeyedhashParms).scheme; TpmAlgId hashAlg = scheme is SchemeHash ? (scheme as SchemeHash).hashAlg : scheme is SchemeXor ? (scheme as SchemeXor).hashAlg : pub.nameAlg; var digestSize = CryptoLib.DigestSize(hashAlg); if (keyData == null) { keyData = Globs.GetRandomBytes(digestSize); } else if (keyData.Length <= CryptoLib.BlockSize(hashAlg)) { keyData = Globs.CopyData(keyData); } else { Globs.Throw <ArgumentException>("HMAC key is too big"); return(null); } newSens = new Tpm2bSensitiveData(keyData); } else { Globs.Throw <ArgumentException>("Unsupported key type"); } return(newSens); }
/// <summary> /// Performs the TPM-defined CFB encrypt using the associated algorithm. /// This routine assumes that the integrity value has been prepended. /// </summary> /// <param name="data"></param> /// <param name="iv"></param> /// <returns></returns> public byte[] Encrypt(byte[] data, byte[] iv = null) { byte[] paddedData; int unpadded = data.Length % BlockSize; paddedData = unpadded == 0 ? data : Globs.AddZeroToEnd(data, BlockSize - unpadded); #if TSS_USE_BCRYPT paddedData = Key.Encrypt(paddedData, null, iv ?? IV); #else bool externalIV = iv != null && iv.Length > 0; if (externalIV) { Alg.IV = iv; } ICryptoTransform enc = Alg.CreateEncryptor(); if (Alg.Mode == CipherMode.ECB && Mode == CipherMode.CFB) { EncryptCFB(paddedData, Alg.IV, enc); } else { using (var outStream = new MemoryStream()) { var s = new CryptoStream(outStream, enc, CryptoStreamMode.Write); s.Write(paddedData, 0, paddedData.Length); s.FlushFinalBlock(); paddedData = outStream.ToArray(); } } if (externalIV) { var src = data; var res = paddedData; if (res.Length > iv.Length) { src = Globs.CopyData(data, src.Length - iv.Length, iv.Length); res = Globs.CopyData(paddedData, res.Length - iv.Length, iv.Length); } switch (Mode) { case CipherMode.CBC: case CipherMode.CFB: res.CopyTo(iv, 0); break; case CipherMode.OFB: XorEngine.Xor(res, src).CopyTo(iv, 0); break; case CipherMode.ECB: break; case CipherMode.CTS: Globs.Throw <ArgumentException>("Encrypt: Unsupported symmetric mode"); break; } } #endif // !TSS_USE_BCRYPT return(unpadded == 0 ? paddedData : Globs.CopyData(paddedData, 0, data.Length)); }
public void SetNonceTpm(byte[] nonceTpm) { NonceTpm = Globs.CopyData(nonceTpm); }
/// <summary> /// Sign using a non-default hash algorithm. /// </summary> /// <param name="data"></param> /// <param name="sigHash"></param> /// <returns></returns> public ISignatureUnion SignData(byte[] data, TpmAlgId sigHash) { #if TSS_USE_BCRYPT Debug.Assert(Key != UIntPtr.Zero); #endif var rsaParams = PublicParms.parameters as RsaParms; if (rsaParams != null) { #if !TSS_USE_BCRYPT Debug.Assert(RsaProvider != null); #endif TpmAlgId sigScheme = rsaParams.scheme.GetUnionSelector(); switch (sigScheme) { case TpmAlgId.Rsassa: { if (sigHash == TpmAlgId.Null) { sigHash = (rsaParams.scheme as SigSchemeRsassa).hashAlg; } byte[] digest = CryptoLib.HashData(sigHash, data); #if TSS_USE_BCRYPT byte[] sig = Key.SignHash(digest, BcryptScheme.Rsassa, sigHash); #else byte[] sig = RsaProvider.SignData(data, CryptoLib.GetHashName(sigHash)); #endif return(new SignatureRsassa(sigHash, sig)); } case TpmAlgId.Rsapss: { #if true Globs.Throw <ArgumentException>("SignData(): PSS scheme is not supported"); return(null); #else if (sigHash == TpmAlgId.Null) { sigHash = (rsaParams.scheme as SigSchemeRsapss).hashAlg; } #if TSS_USE_BCRYPT byte[] sig = BCryptInterface.SignHash(KeyHandle, digest, sigHash, false); #else var rr = new RawRsa(RsaProvider.ExportParameters(false), RsaProvider.KeySize); byte[] sig = rr.PssSign(digest, sigHash); #endif return(new SignatureRsapss(sigHash, sig)); #endif // false } } Globs.Throw <ArgumentException>("Unsupported signature scheme"); return(null); } var eccParms = PublicParms.parameters as EccParms; if (eccParms != null) { if (eccParms.scheme.GetUnionSelector() != TpmAlgId.Ecdsa) { Globs.Throw <ArgumentException>("Unsupported ECC sig scheme"); return(null); } if (sigHash == TpmAlgId.Null) { sigHash = (eccParms.scheme as SigSchemeEcdsa).hashAlg; } byte[] digest = CryptoLib.HashData(sigHash, data); #if TSS_USE_BCRYPT //throw new NotImplementedException("ECC signing with BCrypt is not implemented"); byte[] sig = Key.SignHash(digest, BcryptScheme.Ecdsa, sigHash); int len = sig.Length / 2; return(new SignatureEcdsa(sigHash, Globs.CopyData(sig, 0, len), Globs.CopyData(sig, len, len))); #elif !__MonoCS__ Debug.Assert(EcdsaProvider != null); EcdsaProvider.HashAlgorithm = GetCngAlgorithm(sigHash); byte[] sig = EcdsaProvider.SignData(data); int fragLen = sig.Length / 2; var r = Globs.CopyData(sig, 0, fragLen); var s = Globs.CopyData(sig, fragLen, fragLen); return(new SignatureEcdsa(sigHash, r, s)); #endif // !TSS_USE_BCRYPT && !__MonoCS__ } // Should never be here Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm"); return(null); } // SignData()
/// <summary> /// PSS verify. Note: we expect the caller to do the hash. /// </summary> /// <param name="m"></param> /// <param name="em"></param> /// <param name="sLen"></param> /// <param name="emBits"></param> /// <param name="hashAlg"></param> /// <returns></returns> public static bool PssVerify(byte[] m, byte[] em, int sLen, int emBits, TpmAlgId hashAlg) { var emLen = (int)Math.Ceiling(1.0 * emBits / 8); int hLen = CryptoLib.DigestSize(hashAlg); // 1 - Skip // 2 byte[] mHash = TpmHash.FromData(hashAlg, m); // 3 if (emLen < hLen + sLen + 2) { return(false); } // 4 if (em[em.Length - 1] != 0xbc) { return(false); } // 5 byte[] maskedDB = Globs.CopyData(em, 0, emLen - hLen - 1); byte[] h = Globs.CopyData(em, emLen - hLen - 1, hLen); // 6 int numZeroBits = 8 * emLen - emBits; // First numZero bits is zero in mask byte mask = GetByteMask(numZeroBits); if ((maskedDB[0] & mask) != maskedDB[0]) { return(false); } // 7 byte[] dbMask = CryptoLib.MGF(h, emLen - hLen - 1, hashAlg); // 8 byte[] db = XorEngine.Xor(maskedDB, dbMask); // 9 int numZeroBits2 = 8 * emLen - emBits; byte mask2 = GetByteMask(numZeroBits2); db[0] &= mask2; // 10 for (int j = 0; j < emLen - hLen - sLen - 2; j++) { if (db[j] != 0) { return(false); } } if (db[emLen - hLen - sLen - 1 - 1] != 1) { return(false); } // 11 byte[] salt = Globs.CopyData(db, db.Length - sLen); // 12 byte[] mPrime = Globs.Concatenate(new[] { Globs.ByteArray(8, 0), mHash, salt }); // 13 byte[] hPrime = TpmHash.FromData(hashAlg, mPrime); // 14 bool match = Globs.ArraysAreEqual(h, hPrime); if (match == false) { return(false); } return(true); }
/// <summary> /// Create a new random software key (public and private) matching the parameters in keyParams. /// </summary> /// <param name="keyParams"></param> /// <returns></returns> public AsymCryptoSystem(TpmPublic keyParams) { TpmAlgId keyAlgId = keyParams.type; PublicParms = keyParams.Copy(); switch (keyAlgId) { case TpmAlgId.Rsa: { var rsaParams = keyParams.parameters as RsaParms; #if TSS_USE_BCRYPT Key = Generate(Native.BCRYPT_RSA_ALGORITHM, rsaParams.keyBits); if (Key == UIntPtr.Zero) { Globs.Throw("Failed to generate RSA key"); return; } byte[] blob = Export(Native.BCRYPT_RSAPUBLIC_BLOB); var m = new Marshaller(blob, DataRepresentation.LittleEndian); var header = m.Get <BCryptRsaKeyBlob>(); /*var exponent = */ m.GetArray <byte>((int)header.cbPublicExp); var modulus = m.GetArray <byte>((int)header.cbModulus); #else RsaProvider = new RSACryptoServiceProvider(rsaParams.keyBits); var modulus = RsaProvider.ExportParameters(true).Modulus; #endif var pubId = new Tpm2bPublicKeyRsa(modulus); PublicParms.unique = pubId; break; } #if !__MonoCS__ case TpmAlgId.Ecc: { var eccParms = keyParams.parameters as EccParms; var alg = RawEccKey.GetEccAlg(keyParams); if (alg == null) { Globs.Throw <ArgumentException>("Unknown ECC curve"); return; } #if TSS_USE_BCRYPT Key = Generate(alg, (uint)RawEccKey.GetKeyLength(eccParms.curveID)); #else var keyParmsX = new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowPlaintextExport }; using (CngKey key = CngKey.Create(alg, null, keyParmsX)) { byte[] keyIs = key.Export(CngKeyBlobFormat.EccPublicBlob); CngKey.Import(keyIs, CngKeyBlobFormat.EccPublicBlob); if (keyParams.objectAttributes.HasFlag(ObjectAttr.Sign)) { EcdsaProvider = new ECDsaCng(key); } else { EcDhProvider = new ECDiffieHellmanCng(key); } // Store the public key const int offset = 8; int keySize = 0; switch (eccParms.curveID) { case EccCurve.TpmEccNistP256: case EccCurve.TpmEccBnP256: case EccCurve.TpmEccSm2P256: keySize = 32; break; case EccCurve.TpmEccNistP384: keySize = 48; break; case EccCurve.TpmEccNistP521: keySize = 66; break; default: throw new NotImplementedException(); } var pubId = new EccPoint( Globs.CopyData(keyIs, offset, keySize), Globs.CopyData(keyIs, offset + keySize, keySize)); PublicParms.unique = pubId; } #endif // !TSS_USE_BCRYPT break; } #endif // !__MonoCS__ default: Globs.Throw <ArgumentException>("Algorithm not supported"); break; } }
public static bool OaepDecode(byte[] eMx, byte[] encodingParms, TpmAlgId hashAlg, out byte[] decoded) { decoded = new byte[0]; var em = new byte[eMx.Length + 1]; Array.Copy(eMx, 0, em, 1, eMx.Length); int hLen = CryptoLib.DigestSize(hashAlg); int k = em.Length; // a. byte[] lHash = CryptoLib.HashData(hashAlg, encodingParms); // b. byte y = em[0]; byte[] maskedSeed = Globs.CopyData(em, 1, hLen); byte[] maskedDB = Globs.CopyData(em, 1 + hLen); // c. byte[] seedMask = CryptoLib.MGF(maskedDB, hLen, hashAlg); // d. byte[] seed = XorEngine.Xor(maskedSeed, seedMask); // e. byte[] dbMask = CryptoLib.MGF(seed, k - hLen - 1, hashAlg); // f. byte[] db = XorEngine.Xor(maskedDB, dbMask); // g. byte[] lHashPrime = Globs.CopyData(db, 0, hLen); // Look for the zero.. int j; for (j = hLen; j < db.Length; j++) { if (db[j] == 0) { continue; } if (db[j] == 1) { break; } return(false); } if (j == db.Length - 1) { return(false); } byte[] m = Globs.CopyData(db, j + 1); if (y != 0) { return(false); } if (!Globs.ArraysAreEqual(lHash, lHashPrime)) { return(false); } decoded = m; return(true); }
public TpmPolicyTicket(TpmPublic authorizingKey, byte[] policyRef, TpmSt ticketType) : base("") { AuthorizingKey = authorizingKey; PolicyRef = Globs.CopyData(policyRef); TicketType = ticketType; }
/// <summary> /// This command allows a policy to be bound to a specific set of handles /// without being bound to the parameters of the command. This is most /// useful for commands such as TPM2_Duplicate() and for TPM2_PCR_Event() /// when the referenced PCR requires a policy. /// </summary> public TpmPolicyNameHash(byte[] expectedNameHash, string branchName = "") : base(branchName) { NameHash = Globs.CopyData(expectedNameHash); }
/// <summary> /// Associates the name with the handle. Only needed for transient, persistent /// and NV handles. /// Normally this association is done automatically either by TPM commands /// producing the corresponding handle, or when the handle is passed as a /// parameter to a command requiring HMAC authorization (the name is implicitly /// requested from the TPM by means of TPM2_ReadPublic or TPM2_NV_ReadPublic /// commands). /// Thus this method has to be used only either when Tpm2 object is in the strict /// mode (i.e. it is prohibited to issue commands not explicitly requested by /// the user), or for the sake of performance optimization (if the client code /// has the name pre-computed). /// </summary> /// <param name="name"></param> /// <returns>Reference to this object, which can be used for chaining.</returns> public TpmHandle SetName(byte[] name) { _Name = Globs.CopyData(name); return(this); }
/// <summary> /// Create an AuthValue with the specified value. Note that trailing zeros are not removed. /// </summary> /// <param name="val"></param> public AuthValue(byte[] auth) { AuthVal = Globs.CopyData(auth); }