/// <summary> /// Verify a TPM signature structure of the hash of some data (caller hashes the data that will be verified) /// </summary> /// <param name="signedHash"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifySignatureOverHash(TpmHash signedHash, ISignatureUnion signature) { using (AsymCryptoSystem verifier = AsymCryptoSystem.CreateFrom(this)) { return(verifier.VerifySignatureOverHash(signedHash, signature)); } }
/// <summary> /// The TPM always signs hash-sized data. This version of the VerifySignature /// performs the necessary hashing operation over arbitrarily-length data and /// verifies that the hash is properly signed. /// </summary> /// <param name="data"></param> /// <param name="sig"></param> /// <returns></returns> public bool VerifySignatureOverData(byte[] data, ISignatureUnion sig) { using (AsymCryptoSystem verifier = AsymCryptoSystem.CreateFrom(this)) { return(verifier.VerifySignatureOverData(data, sig)); } }
/// <summary> /// Verify a TPM signature structure of the hash of some data (caller hashes /// the data that will be verified). /// </summary> public bool VerifySignatureOverHash(byte[] digest, ISignatureUnion sig) { using (AsymCryptoSystem verifier = AsymCryptoSystem.CreateFrom(this)) { return(verifier.VerifySignatureOverHash(digest, sig)); } }
/// <summary> /// Verify that quotedInfo is properly signed by an associated private key /// holder, and that the quotedInfo.type, .extraData and .magic are correct. /// Also check that the certified name is what the caller expects. The caller /// must check other fields (for instance the qualified name) /// </summary> /// <param name="name"></param> /// <param name="nonce"></param> /// <param name="quotedInfo"></param> /// <param name="expectedName"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifyCertify(TpmHash name, byte[] nonce, Attest quotedInfo, byte[] expectedName, ISignatureUnion signature) { // Check generic signature stuff if (quotedInfo.type != TpmSt.AttestCertify) { return(false); } if (!Globs.ArraysAreEqual(quotedInfo.extraData, nonce)) { return(false); } if (quotedInfo.magic != Generated.Value) { return(false); } // Check specific certify-signature stuff var certInfo = (CertifyInfo)quotedInfo.attested; if (!Globs.ArraysAreEqual(expectedName, certInfo.name)) { return(false); } // Check the actual signature TpmHash sigHash = TpmHash.FromData(TpmAlgId.Sha1, quotedInfo.GetTpmRepresentation()); bool certifyOk = VerifySignatureOverHash(sigHash, signature); return(certifyOk); }
/// <summary> /// This command allows policies to change. If a policy were static, /// then it would be difficult to add users to a policy. This command lets a /// policy authority sign a new policy so that it may be used in an existing policy. /// </summary> public TpmPolicyAuthorize( byte[] policyToReplace, byte[] policyRef, TpmPublic signingKey, TpmAlgId signingHash, ISignatureUnion signature, string branchName = "") : base(branchName) { PolicyToReplace = Globs.CopyData(policyToReplace); PolicyRef = Globs.CopyData(policyRef); SigningKey = signingKey; SigningHash = signingHash; // todo - this should really be an ISigntatureUnion but the stock serializer // can't serialize interfaces //Signature = (SignatureRsassa)signature; // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull if (signature is SignatureRsapss) { Sig1 = (SignatureRsapss)signature; } // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull if (signature is SignatureRsassa) { Sig2 = (SignatureRsassa)signature; } }
void ExternalKeyImportSample(Tpm2 tpm, TestContext testCtx) { // Create a software key (external to any TPM). int keySize = 2048; var externalRsaKey = new RawRsa(keySize); // When an external key comes from a cert, one would need to extract the key size and // byte buffers representing public and private parts of the key from the cert, an use // them directly in the call to ImportExternalRsaKey() below (i.e. no RawRsa object is // necessary). // Signing scheme to use (it may come from the key's cert) TpmAlgId sigHashAlg = Substrate.Random(TpmCfg.HashAlgs); var sigScheme = new SchemeRsassa(sigHashAlg); // An arbitrary external key would not have TPM key attributes associated with it. // Yet some of them may be inferred from the cert based on the declared key purpose // (ObjectAttr.Sign below). The others are defined by the intended TPM key usage // scenarios, e.g. ObjectAttr.UserWithAuth tells TPM to allow key usage authorization // using an auth value (random byte buffer) in a password or an HMAC session. ObjectAttr keyAttrs = ObjectAttr.Sign | ObjectAttr.UserWithAuth; // Generate an auth value for the imported matching in strength the signing scheme byte[] authVal = Substrate.RandomAuth(sigHashAlg); // We need a storage key to use as a parent of the imported key. // The following helper creates an RSA primary storage key. TpmHandle hParent = Substrate.CreateRsaPrimary(tpm); TssObject importedKey = ImportExternalRsaKey(tpm, hParent, keySize, sigScheme, externalRsaKey.Public, externalRsaKey.Private, keyAttrs, authVal); // Now we can load the newly imported key into the TPM, ... TpmHandle hImportedKey = tpm.Load(hParent, importedKey.Private, importedKey.Public); // ... let the TSS know the auth value associated with this handle, ... hImportedKey.SetAuth(authVal); // ... and use it to sign something to check if import was OK TpmHash toSign = TpmHash.FromRandom(sigHashAlg); ISignatureUnion sig = tpm.Sign(hImportedKey, toSign, null, new TkHashcheck()); // Verify that the signature is correct using the public part of the imported key bool sigOk = importedKey.Public.VerifySignatureOverHash(toSign, sig); testCtx.Assert("Signature.OK", sigOk); // Cleanup tpm.FlushContext(hImportedKey); // The parent key handle can be flushed immediately after it was used in the Load() command tpm.FlushContext(hParent); // Imported private/public key pair (in the TssObject) can be stored on disk, in the cloud, // etc. (no additional protection is necessary), and loaded into the TPM as above whenever // the key is needed. // Alternatively the key can be persisted in the TPM using the EvictControl() command } // ExternalKeyImportSample
/// <summary> /// The TPM always signs hash-sized data. This version of the VerifySignature performs the necessary /// hash operation over arbitrarily-length data and verifies that the hash is properly signed /// (i.e. the library performs the hash) /// </summary> /// <param name="signedData"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifySignatureOverData(byte[] signedData, ISignatureUnion signature, TpmAlgId sigHashAlg = TpmAlgId.Null) { using (AsymCryptoSystem verifier = AsymCryptoSystem.CreateFrom(this)) { bool sigOk = verifier.VerifySignatureOverData(signedData, signature, sigHashAlg); return sigOk; } }
/// <summary> /// The TPM always signs hash-sized data. This version of the VerifySignature performs the necessary /// hash operation over arbitrarily-length data and verifies that the hash is properly signed /// (i.e. the library performs the hash) /// </summary> /// <param name="signedData"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifySignatureOverData(byte[] signedData, ISignatureUnion signature, TpmAlgId sigHashAlg = TpmAlgId.Null) { using (AsymCryptoSystem verifier = AsymCryptoSystem.CreateFrom(this)) { bool sigOk = verifier.VerifySignatureOverData(signedData, signature, sigHashAlg); return(sigOk); } }
/// <summary> /// This is called from TpmPolicySigned when an external caller must sign the session data. /// </summary> /// <returns></returns> internal ISignatureUnion ExecuteSignerCallback(TpmPolicySigned ace, byte[] nonceTpm, out TpmPublic verificationKey) { if (SignerCallback == null) { throw new Exception("No policy signer callback installed."); } ISignatureUnion signature = SignerCallback(this, ace, nonceTpm, out verificationKey); return(signature); }
/// <summary> /// Verify a TPM signature structure of the hash of some data (caller hashes /// the data that will be verified). /// </summary> /// <param name="digest"></param> /// <param name="sig"></param> /// <returns></returns> public bool VerifySignatureOverHash(byte[] digest, ISignatureUnion sig) { if (Public.type == TpmAlgId.Keyedhash) { byte[] hmacKey = (Sensitive.sensitive as Tpm2bSensitiveData).buffer; return(CryptoLib.VerifyHmac(CryptoLib.SchemeHash(sig), hmacKey, digest, (TpmHash)sig)); } else { return(Public.VerifySignatureOverHash(digest, sig)); } }
/// <summary> /// Verify that a TPM quote matches an expect PCR selection, is well formed, /// and is properly signed. /// </summary> /// <param name="pcrDigestAlg"></param> /// <param name="expectedSelectedPcr"></param> /// <param name="expectedPcrValues"></param> /// <param name="nonce"></param> /// <param name="quotedInfo"></param> /// <param name="signature"></param> /// <param name="qualifiedNameOfSigner"></param> /// <returns></returns> public bool VerifyQuote(TpmAlgId pcrDigestAlg, PcrSelection[] expectedSelectedPcr, Tpm2bDigest[] expectedPcrValues, byte[] nonce, Attest quotedInfo, ISignatureUnion signature, byte[] qualifiedNameOfSigner = null) { QuoteElt pointOfFailure; return(VerifyQuote(pcrDigestAlg, expectedSelectedPcr, expectedPcrValues, nonce, quotedInfo, signature, out pointOfFailure, qualifiedNameOfSigner)); }
internal override TpmRc Execute(Tpm2 tpm, AuthSession sess, PolicyTree policy) { byte[] nonceTpm = UseNonceTpm ? Globs.CopyData(sess.NonceTpm) : new byte[0]; TpmHandle sigKey; // If we have both the authorizing signature and the corresponding // signing key handle, we are good to go. if (AuthSig == null) { var dataToSign = new Marshaller(); dataToSign.Put(nonceTpm, ""); // If we have a signing key we can build the challenge here // (else we need to call out) if (SwSigningKey != null) { dataToSign.Put(ExpirationTime, ""); dataToSign.Put(CpHash, ""); dataToSign.Put(PolicyRef, ""); // Just ask the key to sign the challenge AuthSig = SwSigningKey.Sign(dataToSign.GetBytes()); sigKey = tpm.LoadExternal(null, SigningKeyPub, TpmRh.Owner); } else { TpmPublic verifier; AuthSig = AssociatedPolicy.ExecuteSignerCallback(this, nonceTpm, out verifier); sigKey = tpm.LoadExternal(null, verifier, TpmRh.Owner); } } else { sigKey = tpm.LoadExternal(null, SigningKeyPub, TpmRh.Owner); } Timeout = tpm.PolicySigned(sigKey, sess, nonceTpm, CpHash, PolicyRef, ExpirationTime, AuthSig, out Ticket); TpmRc responseCode = tpm._GetLastResponseCode(); tpm.FlushContext(sigKey); if (!KeepAuth) { AuthSig = null; } return(responseCode); }
public static TpmAlgId SchemeHash(ISignatureUnion sig) { if (sig is SignatureRsa) { return((sig as SignatureRsa).hash); } if (sig is SignatureEcc) { return((sig as SignatureEcc).hash); } if (sig is TpmHash) { return((sig as TpmHash).HashAlg); } return(TpmAlgId.Null); }
///<param name = "the_keyHandle">handle of public key that will be used in the validation Auth Index: None</param> ///<param name = "the_digest">digest of the signed message</param> ///<param name = "the_signature">signature to be tested(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2VerifySignatureRequest( TpmHandle the_keyHandle, byte[] the_digest, ISignatureUnion the_signature ) { this.keyHandle = the_keyHandle; this.digest = the_digest; this.signature = the_signature; }
/// <summary> /// Verify a TPM signature structure of the hash of some data (caller hashes the data that will be verified) /// </summary> /// <param name="signedHash"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifySignatureOverHash(TpmHash signedHash, ISignatureUnion signature) { using (AsymCryptoSystem verifier = AsymCryptoSystem.CreateFrom(this)) { return verifier.VerifySignatureOverHash(signedHash, signature); } }
///<param name = "the_certifyInfo">the structure that was signed</param> ///<param name = "the_signature">the signature over certifyInfo(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2CertifyCreationResponse( byte[] the_certifyInfo, ISignatureUnion the_signature ) { this.certifyInfo = the_certifyInfo; this.signature = the_signature; }
///<param name = "the_authorization">TPM_RH_PLATFORM+{PP} Auth Index:1 Auth Role: ADMIN</param> ///<param name = "the_keyHandle">handle of a public area that contains the TPM Vendor Authorization Key that will be used to validate manifestSignature Auth Index: None</param> ///<param name = "the_fuDigest">digest of the first block in the field upgrade sequence</param> ///<param name = "the_manifestSignature">signature over fuDigest using the key associated with keyHandle (not optional)(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2FieldUpgradeStartRequest( TpmHandle the_authorization, TpmHandle the_keyHandle, byte[] the_fuDigest, ISignatureUnion the_manifestSignature ) { this.authorization = the_authorization; this.keyHandle = the_keyHandle; this.fuDigest = the_fuDigest; this.manifestSignature = the_manifestSignature; }
///<param name = "the_auditInfo">the audit information that was signed</param> ///<param name = "the_signature">the signature over auditInfo(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2GetSessionAuditDigestResponse( byte[] the_auditInfo, ISignatureUnion the_signature ) { this.auditInfo = the_auditInfo; this.signature = the_signature; }
} // CreateRsaPrimaryStorageKey() /// <summary> /// This sample illustrates the creation and use of an RSA signing key to /// "quote" PCR state /// </summary> /// <param name="tpm">Reference to the TPM object.</param> static void QuotePcrs(Tpm2 tpm) { Console.WriteLine("\nPCR Quote sample started."); // // First use a library routine to create an RSA/AES primary storage key // with null user-auth. // TpmHandle primHandle = CreateRsaPrimaryStorageKey(tpm); // // Template for a signing key. We will make the key restricted so that we // can quote with it too. // var signKeyPubTemplate = new TpmPublic(TpmAlgId.Sha256, ObjectAttr.Sign | ObjectAttr.Restricted | // A "quoting" key ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable ObjectAttr.UserWithAuth | // Authorize with auth-data ObjectAttr.SensitiveDataOrigin, // TPM will create a new key null, new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0), new Tpm2bPublicKeyRsa()); // // Auth-data for new key // var userAuth = new byte[] { 1, 2, 3, 4 }; var sensCreate = new SensitiveCreate(userAuth, null); // // Creation data (not used in this sample) // CreationData childCreationData; TkCreation creationTicket; byte[] creationHash; // // Create the key // TpmPublic keyPub; TpmPrivate keyPriv = tpm.Create(primHandle, // Child of primary key created above sensCreate, // Auth-data signKeyPubTemplate, // Template created above null, // Other parms are not used here new PcrSelection[0], // Not bound to any PCRs out keyPub, out childCreationData, out creationHash, out creationTicket); Console.WriteLine("New public key\n" + keyPub.ToString()); // // Load the key as a child of the primary that it // was created under. // TpmHandle hSigKey = tpm.Load(primHandle, keyPriv, keyPub); // // Note that Load returns the "name" of the key and this is automatically // associated with the handle. // Console.WriteLine("Name of key:" + BitConverter.ToString(hSigKey.Name)); // // A nonce (or qualifying data) // TpmHash nonce = TpmHash.FromData(TpmAlgId.Sha256, new byte[] { 4, 3, 2, 1 }); // // PCRs to quote. SHA-256 bank, PCR-indices 1, 2, and 3 // var pcrsToQuote = new PcrSelection[] { new PcrSelection(TpmAlgId.Sha256, new uint[] { 1, 2, 3 }) }; // // Ask the TPM to quote the PCR (with the given nonce). The TPM // returns both the signature and the quote data that were signed. // ISignatureUnion quoteSig; Attest quotedInfo = tpm.Quote(hSigKey, nonce, new SchemeRsassa(TpmAlgId.Sha256), pcrsToQuote, out quoteSig); // // Print out what was quoted // var info = (QuoteInfo)quotedInfo.attested; Console.WriteLine("PCRs that were quoted: " + info.pcrSelect[0].ToString() + "\nHash of PCR-array: " + BitConverter.ToString(info.pcrDigest)); // // Read the PCR to check the quoted value // PcrSelection[] outSelection; Tpm2bDigest[] outValues; tpm.PcrRead(new PcrSelection[] { new PcrSelection(TpmAlgId.Sha256, new uint[] { 1, 2, 3 }) }, out outSelection, out outValues); // // Use the TSS.Net library to validate the quote against the // values just read. // bool quoteOk = keyPub.VerifyQuote(TpmAlgId.Sha256, outSelection, outValues, nonce, quotedInfo, quoteSig); if (!quoteOk) { throw new Exception("Quote did not validate"); } Console.WriteLine("Quote correctly validated."); // // Test other uses of the signing key. A restricted key can only // sign data that the TPM knows does not start with a magic // number (that identifies TPM internal data). So this does not // work // var nullProof = new TkHashcheck(TpmHandle.RhNull, null); tpm._ExpectError(TpmRc.Ticket) .Sign(hSigKey, nonce, new SchemeRsassa(TpmAlgId.Sha256), nullProof); // // But if we ask the TPM to hash the same data and then sign it // then the TPM can be sure that the data is safe, so it will // sign it. // TkHashcheck tkSafeHash; TpmHandle hashHandle = tpm.HashSequenceStart(null, TpmAlgId.Sha256); // // The ticket is only generated if the data is "safe." // tpm.SequenceComplete(hashHandle, new byte[] { 4, 3, 2, 1 }, TpmRh.Owner, out tkSafeHash); // // This will now work because the ticket proves to the // TPM that the data that it is about to sign does not // start with TPM_GENERATED // ISignatureUnion sig = tpm.Sign(hSigKey, nonce, new SchemeRsassa(TpmAlgId.Sha256), tkSafeHash); // // And we can verify the signature // bool sigOk = keyPub.VerifySignatureOverData(new byte[] { 4, 3, 2, 1 }, sig); if (!sigOk) { throw new Exception("Signature did not verify"); } Console.WriteLine("Signature verified."); // // Clean up // tpm.FlushContext(primHandle); tpm.FlushContext(hSigKey); Console.WriteLine("PCR Quote sample finished."); } // QuotePcrs()
///<param name = "the_auditInfo">the auditInfo that was signed</param> ///<param name = "the_signature">the signature over auditInfo(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2GetCommandAuditDigestResponse( Attest the_auditInfo, ISignatureUnion the_signature ) { this.auditInfo = the_auditInfo; this.signature = the_signature; }
/// <summary> /// Verifies the signature over data or a digest. /// The data will be hashed internall by the method using hash algorithm from /// the signing scheme digest computed from the specified data buffer. /// The signing scheme is retrieved from the signature. The verification key /// shall have either compatible or null scheme. /// </summary> /// <param name="data">Byte buffer containing either digest or data to check against the signature</param> /// <param name="dataIsDigest">Specifies the type of 'data' parameter contents</param> /// <param name="signature">The signature</param> /// <returns>True if the verification succeeds.</returns> private bool VerifySignature(byte[] data, bool dataIsDigest, ISignatureUnion sig) { #if TSS_USE_BCRYPT Debug.Assert(Key != UIntPtr.Zero); #endif TpmAlgId sigScheme = sig.GetUnionSelector(); TpmAlgId sigHash = CryptoLib.SchemeHash(sig); var rsaParams = PublicParms.parameters as RsaParms; if (rsaParams != null) { #if !TSS_USE_BCRYPT Debug.Assert(RsaProvider != null); #endif var s = sig as SignatureRsa; TpmAlgId keyScheme = rsaParams.scheme.GetUnionSelector(); if (keyScheme != TpmAlgId.Null && keyScheme != sigScheme) { Globs.Throw <ArgumentException>("Key scheme and signature scheme do not match"); return(false); } byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); if (sigScheme == TpmAlgId.Rsassa) { #if TSS_USE_BCRYPT return(Key.VerifySignature(digest, s.sig, sigHash, true)); #else return(RsaProvider.VerifyHash(digest, CryptoLib.GetHashName(sigHash), s.sig)); #endif } if (sigScheme == TpmAlgId.Rsapss) { #if true Globs.Throw <ArgumentException>("VerifySignature(): PSS scheme is not supported"); return(false); #else #if TSS_USE_BCRYPT return(BCryptInterface.VerifySignature(KeyHandle, digest, sig.sig, sigHash, false)); #else var rr = new RawRsa(RsaProvider.ExportParameters(false), RsaProvider.KeySize); return(rr.PssVerify(digest, sig.sig, sigHash)); #endif #endif // false } Globs.Throw <ArgumentException>("VerifySignature(): Unrecognized scheme"); return(false); } var eccParams = PublicParms.parameters as EccParms; if (eccParams != null) { if (eccParams.scheme.GetUnionSelector() != TpmAlgId.Ecdsa) { Globs.Throw <ArgumentException>("Unsupported ECC sig scheme"); return(false); } TpmAlgId keyScheme = eccParams.scheme.GetUnionSelector(); if (keyScheme != TpmAlgId.Null && keyScheme != sigScheme) { Globs.Throw <ArgumentException>("Key scheme and signature scheme do not match"); return(false); } var s = sig as SignatureEcdsa; byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); byte[] sigBlob = Globs.Concatenate(s.signatureR, s.signatureS); #if TSS_USE_BCRYPT return(Key.VerifySignature(digest, sigBlob)); #elif !__MonoCS__ Debug.Assert(EcdsaProvider != null); EcdsaProvider.HashAlgorithm = GetCngAlgorithm(sigHash); return(EcdsaProvider.VerifyHash(digest, sigBlob)); #endif // !TSS_USE_BCRYPT && !__MonoCS__ } // Should never be here Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm"); return(false); } // VerifySignature()
public void FieldUpgradeStart( TpmHandle authorization, TpmHandle keyHandle, byte[] fuDigest, ISignatureUnion manifestSignature ) { Tpm2FieldUpgradeStartRequest inS = new Tpm2FieldUpgradeStartRequest(); inS.authorization = authorization; inS.keyHandle = keyHandle; inS.fuDigest = fuDigest; inS.manifestSignature = manifestSignature; TpmStructureBase outSBase; DispatchMethod(TpmCc.FieldUpgradeStart, (TpmStructureBase) inS, typeof(Tpm2FieldUpgradeStartResponse), out outSBase, 2, 0); }
///<param name = "the_signature">This shall be the actual signature information.(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Signature( ISignatureUnion the_signature ) { this.signature = the_signature; }
public byte[] PolicySigned( TpmHandle authObject, TpmHandle policySession, byte[] nonceTPM, byte[] cpHashA, byte[] policyRef, int expiration, ISignatureUnion auth, [SuppressMessage("Microsoft.Design", "CA1021")] out TkAuth policyTicket ) { Tpm2PolicySignedRequest inS = new Tpm2PolicySignedRequest(); inS.authObject = authObject; inS.policySession = policySession; inS.nonceTPM = nonceTPM; inS.cpHashA = cpHashA; inS.policyRef = policyRef; inS.expiration = expiration; inS.auth = auth; TpmStructureBase outSBase; DispatchMethod(TpmCc.PolicySigned, (TpmStructureBase) inS, typeof(Tpm2PolicySignedResponse), out outSBase, 2, 0); Tpm2PolicySignedResponse outS = (Tpm2PolicySignedResponse) outSBase; policyTicket = outS.policyTicket; return outS.timeout; }
public TkVerified VerifySignature( TpmHandle keyHandle, byte[] digest, ISignatureUnion signature ) { Tpm2VerifySignatureRequest inS = new Tpm2VerifySignatureRequest(); inS.keyHandle = keyHandle; inS.digest = digest; inS.signature = signature; TpmStructureBase outSBase; DispatchMethod(TpmCc.VerifySignature, (TpmStructureBase) inS, typeof(Tpm2VerifySignatureResponse), out outSBase, 1, 0); Tpm2VerifySignatureResponse outS = (Tpm2VerifySignatureResponse) outSBase; return outS.validation; }
///<param name = "the_certifyInfo">the structure that was signed</param> ///<param name = "the_signature">the asymmetric signature over certifyInfo using the key referenced by signHandle(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2NvCertifyResponse( Attest the_certifyInfo, ISignatureUnion the_signature ) { this.certifyInfo = the_certifyInfo; this.signature = the_signature; }
} // SignData() /// <summary> /// Verifies the signature over a digest. /// The signing scheme is retrieved from the signature. The verification key /// shall have either compatible or null scheme. /// </summary> /// <param name="digest">Digest to check against the signature</param> /// <param name="signature">The signature</param> /// <returns>True if the verification succeeds.</returns> public bool VerifySignatureOverHash(byte[] digest, ISignatureUnion signature) { return(VerifySignature(digest ?? new byte[0], true, signature)); }
///<param name = "the_quoted">the quoted information</param> ///<param name = "the_signature">the signature over quoted(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2QuoteResponse( Attest the_quoted, ISignatureUnion the_signature ) { this.quoted = the_quoted; this.signature = the_signature; }
/// <summary> /// Verifies the signature over data. /// The data will be hashed internall by the method using hash algorithm from /// the signing scheme digest computed from the specified data buffer. /// The signing scheme is retrieved from the signature. The verification key /// shall have either compatible or null scheme. /// </summary> /// <param name="signedData">Data buffer to check against the signature</param> /// <param name="signature">The signature</param> /// <returns>True if the verification succeeds.</returns> public bool VerifySignatureOverData(byte[] signedData, ISignatureUnion signature) { return(VerifySignature(signedData, false, signature)); }
public TkVerified VerifySignatureOfRecivedMessage(TpmPublic keyPublic, byte[] message, ISignatureUnion signature) { TpmHash dataToSign = TpmHash.FromData(TpmAlgId.Sha256, message); TpmHandle pubHandle = tpm.LoadExternal(null, keyPublic, TpmHandle.RhOwner); return(tpm.VerifySignature(pubHandle, dataToSign.HashData, signature)); }
private bool VerifySignature(byte[] data, bool dataIsDigest, ISignatureUnion signature, TpmAlgId sigHash) { var rsaParams = PublicParms.parameters as RsaParms; if (rsaParams != null) { var sig = signature as SignatureRsa; TpmAlgId sigScheme = sig.GetUnionSelector(); TpmAlgId keyScheme = rsaParams.scheme.GetUnionSelector(); if (keyScheme != TpmAlgId.Null && keyScheme != sigScheme) { Globs.Throw <ArgumentException>("Key scheme and signature scheme do not match"); return(false); } if (sigHash == TpmAlgId.Null) { sigHash = (rsaParams.scheme as SchemeHash).hashAlg; } if (sigHash != sig.hash) { Globs.Throw <ArgumentException>("Key scheme hash and signature scheme hash do not match"); return(false); } byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); if (sigScheme == TpmAlgId.Rsassa) { return(CryptographicEngine.VerifySignatureWithHashInput(Key, CryptographicBuffer.CreateFromByteArray(digest), CryptographicBuffer.CreateFromByteArray(sig.sig))); } if (sigScheme == TpmAlgId.Rsapss) { Globs.Throw <ArgumentException>("VerifySignature(): PSS scheme is not supported"); return(false); } Globs.Throw <ArgumentException>("VerifySignature(): Unrecognized scheme"); return(false); } var eccParms = PublicParms.parameters as EccParms; if (eccParms != null) { if (eccParms.scheme.GetUnionSelector() != TpmAlgId.Ecdsa) { Globs.Throw <ArgumentException>("Unsupported ECC sig scheme"); return(false); } if (sigHash == TpmAlgId.Null) { sigHash = (eccParms.scheme as SigSchemeEcdsa).hashAlg; } byte[] digest = dataIsDigest ? data : CryptoLib.HashData(sigHash, data); var sig = signature as SignatureEcdsa; byte[] sigBlob = Globs.Concatenate(sig.signatureR, sig.signatureS); return(CryptographicEngine.VerifySignatureWithHashInput(Key, CryptographicBuffer.CreateFromByteArray(digest), CryptographicBuffer.CreateFromByteArray(sigBlob))); } // Should never be here Globs.Throw("VerifySignature: Unrecognized asymmetric algorithm"); return(false); } // VerifySignature()
/// <summary> /// Verifies the signature over the digest computed from the specified data buffer. /// /// If sigHashAlg parameter specifies non-null hash algorithm, it is used to compute /// the digest and for the signature checking purposes. Otherwise the hash from /// the signing scheme of the signing key specification is used. /// /// NOTE: Procedure of the hash algorithm selection used by this method does /// not attempt to reproduce the the one used by the TPM. /// </summary> /// <param name="signedData">Data buffer used to check against the signature</param> /// <param name="signature">The signature</param> /// <param name="sigHashAlg">Optional hash algorithm to override the one in the signing key specification</param> /// <returns>True if the verification succeeds.</returns> public bool VerifySignatureOverData(byte[] signedData, ISignatureUnion signature, TpmAlgId sigHashAlg = TpmAlgId.Null) { return(VerifySignature(signedData, false, signature, sigHashAlg)); }
/// <summary> /// The callback to sign the TpmPolicySignature challenge from the TPM. /// </summary> /// <param name="policyTree">The policy tree to check.</param> /// <param name="ace">The policy element (TpmPolicySignature) to evaluate.</param> /// <param name="nonceTpm">The nonce from the TPM.</param> /// <returns>Signature of the nonce.</returns> public static ISignatureUnion SignerCallback(PolicyTree policyTree, TpmPolicySigned ace, byte[] nonceTpm, out TpmPublic verificationKey) { // // This function checks the parameters of the associated TpmPolicySigned // ACE, and if they are those expected the TPM challenge is signed. // Note that policy expressions are often obtained from untrustworthy // sources, so it is important for key-holders to check what they // are bing asked to do before signing anything. // // // The policy just contains the name of the signature verification key, however the // TPM needs the actual public key to verify the signature. Check that the name // matches, and if it does return the public key. // byte[] expectedName = _publicSigningKey.GetPublicParms().GetName(); if (!expectedName.SequenceEqual(ace.AuthObjectName)) { throw new Exception("Unexpected name in policy."); } verificationKey = _publicSigningKey.GetPublicParms(); // // Check that the key is the one that we expect // if (ace.NodeId != "Signing Key 1") { throw new Exception("Unrecognized key"); } // // Check that nonceTom is not null (otherwise anything we sign can // be used for any session). // if (nonceTpm.Length == 0) { throw new Exception("Sign challenges with expiration time need nonce."); } // // Check PolicyRef and cpHash are what we want to sign // if (ace.CpHash.Length != 0) { throw new Exception("I only sign null-cpHash"); } if (!ace.PolicyRef.SequenceEqual(new byte[] { 1, 2, 3, 4 })) { throw new Exception("Incorrect PolicyRef"); } // // And finally check that the expiration is set correctly. Check for // positive values (simple signing policy) and negative values (sining // policy with ticket). // if (ace.ExpirationTime != _expectedExpirationTime) { throw new Exception("Unexpected expiration time"); } // // Everything is OK, so get a formatted bloc containing the challenge // data and then sign it. // byte[] dataStructureToSign = PolicyTree.GetDataStructureToSign(ace.ExpirationTime, nonceTpm, ace.CpHash, ace.PolicyRef); ISignatureUnion signature = _publicSigningKey.Sign(dataStructureToSign); return(signature); }
/// <summary> // Verify that a TPM quote matches an expect PCR selection, is well formed, // and is properly signed. In acse of failure this overload additionally // returns information about the specific check that failed. /// </summary> /// <param name="pcrDigestAlg"></param> /// <param name="expectedSelectedPcr"></param> /// <param name="expectedPcrValues"></param> /// <param name="nonce"></param> /// <param name="quotedInfo"></param> /// <param name="signature"></param> /// <param name="pointOfFailure"></param> /// <param name="qualifiedNameOfSigner"></param> /// <returns></returns> public bool VerifyQuote(TpmAlgId pcrDigestAlg, PcrSelection[] expectedSelectedPcr, Tpm2bDigest[] expectedPcrValues, byte[] nonce, Attest quotedInfo, ISignatureUnion signature, out QuoteElt pointOfFailure, byte[] qualifiedNameOfSigner = null) { pointOfFailure = QuoteElt.None; if (!(quotedInfo.attested is QuoteInfo)) { pointOfFailure = QuoteElt.Type; return(false); } if (quotedInfo.magic != Generated.Value) { pointOfFailure = QuoteElt.Magic; return(false); } if (!quotedInfo.extraData.IsEqual(nonce)) { pointOfFailure = QuoteElt.ExtraData; return(false); } // Check environment of signer (name) is expected if (qualifiedNameOfSigner != null && !quotedInfo.qualifiedSigner.IsEqual(qualifiedNameOfSigner)) { pointOfFailure = QuoteElt.QualifiedSigner; return(false); } // Now check the quote-specific fields var quoted = (QuoteInfo)quotedInfo.attested; // Check values pcr indices are what we expect if (!Globs.ArraysAreEqual(quoted.pcrSelect, expectedSelectedPcr)) { pointOfFailure = QuoteElt.PcrSelect; return(false); } // Check that values in the indices above are what we expect // ReSharper disable once UnusedVariable var expected = new PcrValueCollection(expectedSelectedPcr, expectedPcrValues); var m = new Marshaller(); foreach (Tpm2bDigest d in expectedPcrValues) { m.Put(d.buffer, ""); } TpmHash expectedPcrHash = TpmHash.FromData(pcrDigestAlg, m.GetBytes()); if (!Globs.ArraysAreEqual(expectedPcrHash, quoted.pcrDigest)) { pointOfFailure = QuoteElt.PcrDigest; return(false); } // And finally check the signature if (!VerifySignatureOverData(quotedInfo.GetTpmRepresentation(), signature)) { pointOfFailure = QuoteElt.Signature; return(false); } return(true); }
///<param name = "the_signature">the signature(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2SignResponse( ISignatureUnion the_signature ) { this.signature = the_signature; }
/// <summary> /// The TPM always signs hash-sized data. This version of the VerifySignature /// performs the necessary hashing operation over arbitrarily-length data and /// verifies that the hash is properly signed. /// </summary> /// <param name="data"></param> /// <param name="sig"></param> /// <returns></returns> public bool VerifySignatureOverData(byte[] data, ISignatureUnion sig) { byte[] digest = CryptoLib.HashData(CryptoLib.SchemeHash(sig), data); return(VerifySignatureOverHash(digest, sig)); }
/// <summary> /// Verify that a TPM quote matches an expect PCR selection, is well formed, and is properly signed /// by the private key corresponding to this public key. /// </summary> /// <param name="pcrDigestAlg"></param> /// <param name="expectedSelectedPcr"></param> /// <param name="expectedPcrValues"></param> /// <param name="nonce"></param> /// <param name="quotedInfo"></param> /// <param name="signature"></param> /// <param name="qualifiedNameOfSigner"></param> /// <returns></returns> public bool VerifyQuote( TpmAlgId pcrDigestAlg, PcrSelection[] expectedSelectedPcr, Tpm2bDigest[] expectedPcrValues, byte[] nonce, Attest quotedInfo, ISignatureUnion signature, byte[] qualifiedNameOfSigner = null) { if (!(quotedInfo.attested is QuoteInfo)) { return false; } if (quotedInfo.magic != Generated.Value) { return false; } if (!quotedInfo.extraData.IsEqual(nonce)) { return false; } // Check environment of signer (name) is expected if (qualifiedNameOfSigner != null) { if (!quotedInfo.qualifiedSigner.IsEqual(qualifiedNameOfSigner)) { return false; } } // Now check the quote-specific fields var quoted = (QuoteInfo)quotedInfo.attested; // Check values pcr indices are what we expect if (!Globs.ArraysAreEqual(quoted.pcrSelect, expectedSelectedPcr)) { return false; } // Check that values in the indices above are what we expect // ReSharper disable once UnusedVariable var expected = new PcrValueCollection(expectedSelectedPcr, expectedPcrValues); var m = new Marshaller(); foreach (Tpm2bDigest d in expectedPcrValues) { m.Put(d.buffer, ""); } TpmHash expectedPcrHash = TpmHash.FromData(pcrDigestAlg, m.GetBytes()); if (!Globs.ArraysAreEqual(expectedPcrHash, quoted.pcrDigest)) { return false; } // And finally check the signature bool sigOk = VerifySignatureOverData(quotedInfo.GetTpmRepresentation(), signature); return sigOk; }
///<param name = "the_authObject">handle for a key that will validate the signature Auth Index: None</param> ///<param name = "the_policySession">handle for the policy session being extended Auth Index: None</param> ///<param name = "the_nonceTPM">the policy nonce for the session This can be the Empty Buffer.</param> ///<param name = "the_cpHashA">digest of the command parameters to which this authorization is limited This is not the cpHash for this command but the cpHash for the command to which this policy session will be applied. If it is not limited, the parameter will be the Empty Buffer.</param> ///<param name = "the_policyRef">a reference to a policy relating to the authorization may be the Empty Buffer Size is limited to be no larger than the nonce size supported on the TPM.</param> ///<param name = "the_expiration">time when authorization will expire, measured in seconds from the time that nonceTPM was generated If expiration is non-negative, a NULL Ticket is returned. See 23.2.5.</param> ///<param name = "the_auth">signed authorization (not optional)(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2PolicySignedRequest( TpmHandle the_authObject, TpmHandle the_policySession, byte[] the_nonceTPM, byte[] the_cpHashA, byte[] the_policyRef, int the_expiration, ISignatureUnion the_auth ) { this.authObject = the_authObject; this.policySession = the_policySession; this.nonceTPM = the_nonceTPM; this.cpHashA = the_cpHashA; this.policyRef = the_policyRef; this.expiration = the_expiration; this.auth = the_auth; }
public bool VerifySignatureOfRecivedMessageOffTPM(TpmPublic keyPublic, byte[] message, ISignatureUnion signature) { return(keyPublic.VerifySignatureOverData(message, signature)); }
/// <summary> /// Verify that quotedInfo is properly signed by an associated private key holder, and that the /// quotedInfo.type, .extraData and .magic are correct. Also check that the certified name is what /// the caller expects. The caller must check other fields (for instance the qualified name) /// </summary> /// <param name="name"></param> /// <param name="nonce"></param> /// <param name="quotedInfo"></param> /// <param name="expectedName"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifyCertify(TpmHash name, byte[] nonce, Attest quotedInfo, byte[] expectedName, ISignatureUnion signature) { // Check generic signature stuff if (quotedInfo.type != TpmSt.AttestCertify) { return false; } if (!Globs.ArraysAreEqual(quotedInfo.extraData, nonce)) { return false; } if (quotedInfo.magic != Generated.Value) { return false; } // Check specific certify-signature stuff var certInfo = (CertifyInfo)quotedInfo.attested; if (!Globs.ArraysAreEqual(expectedName, certInfo.name)) { return false; } // Check the actual signature TpmHash sigHash = TpmHash.FromData(TpmAlgId.Sha1, quotedInfo.GetTpmRepresentation()); bool certifyOk = VerifySignatureOverHash(sigHash, signature); return certifyOk; }
/// <summary> /// This command allows policies to change. If a policy were static, /// then it would be difficult to add users to a policy. This command lets a /// policy authority sign a new policy so that it may be used in an existing policy. /// </summary> public TpmPolicyAuthorize( byte[] policyToReplace, byte[] policyRef, TpmPublic signingKey, TpmAlgId signingHash, ISignatureUnion signature, string branchName = "") : base(branchName) { PolicyToReplace = Globs.CopyData(policyToReplace); PolicyRef = Globs.CopyData(policyRef); SigningKey = signingKey; SigningHash = signingHash; // todo - this should really be an ISigntatureUnion but the stock serializer // can't serialize interfaces //Signature = (SignatureRsassa)signature; // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull if (signature is SignatureRsapss) { Sig1 = (SignatureRsapss) signature; } // ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull if (signature is SignatureRsassa) { Sig2 = (SignatureRsassa) signature; } }
///<param name = "the_timeInfo">standard TPM-generated attestation block</param> ///<param name = "the_signature">the signature over timeInfo(One of SignatureRsassa, SignatureRsapss, SignatureEcdsa, SignatureEcdaa, SignatureSm2, SignatureEcschnorr, TpmHash, SchemeHash, NullSignature)</param> public Tpm2GetTimeResponse( Attest the_timeInfo, ISignatureUnion the_signature ) { this.timeInfo = the_timeInfo; this.signature = the_signature; }
} // SignData() /// <summary> /// Verifies the signature over a digest. /// /// If sigHashAlg parameter specifies non-null hash algorithm, it is used for /// the signature checking purposes. Otherwise the hash from the signing scheme /// of the signing key specification is used. /// /// NOTE: Procedure of the hash algorithm selection used by this method does /// not attempt to reproduce the the one used by the TPM. /// </summary> /// <param name="signedData">Digest to check against the signature</param> /// <param name="signature">The signature</param> /// <param name="sigHashAlg">Optional hash algorithm to override the one in the signing key specification</param> /// <returns>True if the verification succeeds.</returns> public bool VerifySignatureOverHash(byte[] digest, ISignatureUnion signature, TpmAlgId sigHashAlg = TpmAlgId.Null) { return(VerifySignature(digest, true, signature, sigHashAlg)); }
/// <summary> /// Performs the following operations: /// - Generates in software (using TSS.net helpers) a key with the given template, /// - Creates TPM-compatible dupliction blob for the given TPM based parent key, /// - Import the duplication blob into TPM /// - Loads the imported key into the TPM /// - Makes sure that the imported key works. /// </summary> /// <param name="tpm">TPM instance to use</param> /// <param name="keyPub">Template for the software generated key.</param> /// <param name="hParent">Intended TPM based parent key for the software generated key.</param> /// <param name="innerSymDef">Specification of the optional inner wrapper for the duplication blob.</param> static void GenerateAndImport(Tpm2 tpm, TpmPublic keyPub, TpmHandle hParent, SymDefObject innerSymDef = null) { // // Create a software key with the given template // // Generate a random auth value for the key to be created (though we could // use an empty buffer, too). var keyAuth = AuthValue.FromRandom(CryptoLib.DigestSize(keyPub.nameAlg)); // Generate the key TssObject swKey = TssObject.Create(keyPub, keyAuth); // // Create duplication blob for the new key with the SRK as the new parent // // Create a symmetric software key if an inner wrapper is requested. var innerWrapKey = innerSymDef == null ? null : SymCipher.Create(innerSymDef); // Retrieve the public area of the intended parent key from the TPM // We do not need the name (and qualified name) of the key here, but // the TPM command returns them anyway. // NOTE - Alternatively we could get the public area from the overloaded // form of the CreateRsaPrimaryStorageKey() helper used to create the parent // key, as all TPM key creation commands (TPM2_CreatePrimary(), TPM2_Create() // and TPM2_CreateLoaded()) return it. byte[] name, qname; TpmPublic pubParent = tpm.ReadPublic(hParent, out name, out qname); byte[] encSecret; TpmPrivate dupBlob = swKey.GetDuplicationBlob(pubParent, innerWrapKey, out encSecret); // Import the duplication blob into the TPM TpmPrivate privImp = tpm.Import(hParent, innerWrapKey, swKey.Public, dupBlob, encSecret, innerSymDef ?? new SymDefObject()); // Load the imported key ... TpmHandle hKey = tpm.Load(hParent, privImp, swKey.Public) .SetAuth(swKey.Sensitive.authValue); // ... and validate that it works byte[] message = Globs.GetRandomBytes(32); if (keyPub.objectAttributes.HasFlag(ObjectAttr.Decrypt)) { // Encrypt something if (keyPub.type == TpmAlgId.Symcipher) { // Only need software symcypher here to query IV size. // Normally, when you use a fixed algorithm, you can hardcode it. var swSym = SymCipher.Create(keyPub.parameters as SymDefObject); byte[] ivIn = Globs.GetRandomBytes(swSym.IVSize), ivOut = null; byte[] cipher = swKey.Encrypt(message, ref ivIn, out ivOut); // Not all TPMs implement TPM2_EncryptDecrypt() command tpm._ExpectResponses(TpmRc.Success, TpmRc.TbsCommandBlocked); byte[] decrypted = tpm.EncryptDecrypt(hKey, 1, TpmAlgId.Null, ivIn, cipher, out ivOut); if (tpm._LastCommandSucceeded()) { bool decOk = Globs.ArraysAreEqual(message, decrypted); Console.WriteLine("Imported symmetric key validation {0}", decOk ? "SUCCEEDED" : "FAILED"); } } } else { // Sign something (works for both asymmetric and MAC keys) string keyType = keyPub.type == TpmAlgId.Rsa ? "RSA" : keyPub.type == TpmAlgId.Keyedhash ? "HMAC" : "UNKNOWN"; // Should not happen in this sample TpmAlgId sigHashAlg = GetSchemeHash(keyPub); TpmHash toSign = TpmHash.FromData(sigHashAlg, message); var proofx = new TkHashcheck(TpmRh.Null, null); ISignatureUnion sig = tpm.Sign(hKey, toSign, null, proofx); bool sigOk = swKey.VerifySignatureOverHash(toSign, sig); Console.WriteLine("Imported {0} key validation {1}", keyType, sigOk ? "SUCCEEDED" : "FAILED"); } // Free TPM resources taken by the loaded imported key tpm.FlushContext(hKey); } // GenerateAndImport