Namyoon Woo | f442814 | 2019-10-30 19:02:58 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2019 The Chromium OS Authors. All rights reserved. |
| 3 | * Use of this source code is governed by a BSD-style license that can be |
| 4 | * found in the LICENSE file. |
| 5 | */ |
| 6 | #include "InternalRoutines.h" |
| 7 | #include "PolicyFidoSigned_fp.h" |
| 8 | |
| 9 | /* |
| 10 | * PolicyFidoContextUpdate |
| 11 | * |
| 12 | * @param commandCode IN: TPM Ext command code |
| 13 | * @param name IN: name of entity |
| 14 | * @param in IN: input buffer of the command |
| 15 | * @param policyTimeout IN: policy timeout |
| 16 | * @param session IN/OUT: policy session to be updated |
| 17 | * @return none |
| 18 | */ |
| 19 | static void PolicyFidoContextUpdate(TPM_CC commandCode, |
| 20 | TPM2B_NAME *entityName, |
| 21 | PolicyFidoSigned_In *in, |
| 22 | SESSION *session) |
| 23 | { |
| 24 | HASH_STATE hashState; |
| 25 | UINT16 policyDigestSize; |
| 26 | int i; |
| 27 | |
| 28 | /* Start hash */ |
| 29 | policyDigestSize = CryptStartHash(session->authHashAlg, &hashState); |
| 30 | |
| 31 | /* |
| 32 | * policyDigest size should always be the digest size of session hash |
| 33 | * algorithm. |
| 34 | */ |
| 35 | pAssert(session->u2.policyDigest.t.size == policyDigestSize); |
| 36 | |
| 37 | /* add old digest */ |
| 38 | CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b); |
| 39 | |
| 40 | /* add commandCode */ |
| 41 | CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode); |
| 42 | |
| 43 | /* add name if applicable */ |
| 44 | if (entityName != NULL) |
| 45 | CryptUpdateDigest2B(&hashState, &entityName->b); |
| 46 | |
| 47 | /* Complete the digest and get the results */ |
| 48 | CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b); |
| 49 | |
| 50 | /* Start second hash computation */ |
| 51 | CryptStartHash(session->authHashAlg, &hashState); |
| 52 | |
| 53 | /* add policy digest */ |
| 54 | CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b); |
| 55 | |
| 56 | /* add authDataDescr */ |
| 57 | CryptUpdateDigest(&hashState, |
| 58 | in->authDataDescrCount * sizeof(DATA_OFFSET), |
| 59 | (BYTE *)in->authDataDescr); |
| 60 | |
| 61 | /* add authData[authDataDescr] */ |
| 62 | for (i = 0; i < in->authDataDescrCount; i++) { |
| 63 | CryptUpdateDigest(&hashState, |
| 64 | in->authDataDescr[i].size, |
| 65 | &(in->authData.t.buffer[in->authDataDescr[i].offset])); |
| 66 | } |
| 67 | |
| 68 | /* Complete second digest */ |
| 69 | CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b); |
| 70 | |
| 71 | return; |
| 72 | } |
| 73 | |
| 74 | TPM_RC TPM2_PolicyFidoSigned(PolicyFidoSigned_In *in, |
| 75 | PolicyFidoSigned_Out *out) |
| 76 | { |
| 77 | TPM_RC result = TPM_RC_SUCCESS; |
| 78 | SESSION *session; |
| 79 | TPM2B_NAME entityName; |
| 80 | |
| 81 | session = SessionGet(in->policySession); |
| 82 | |
| 83 | /* Only do input validation if this is not a trial policy session */ |
| 84 | if (session->attributes.isTrialPolicy == CLEAR) { |
| 85 | TPM2B_DIGEST authHash; |
| 86 | HASH_STATE hashState; |
| 87 | |
| 88 | /* |
| 89 | * Re-compute the digest being signed: |
| 90 | * |
| 91 | * aHash := hash (authenticatorData[] || nonceTPM) |
| 92 | * |
| 93 | * Start hash |
| 94 | */ |
| 95 | authHash.t.size = CryptStartHash(CryptGetSignHashAlg(&in->auth), |
| 96 | &hashState); |
| 97 | |
| 98 | /* add authData */ |
| 99 | CryptUpdateDigest(&hashState, |
| 100 | in->authData.t.size, |
| 101 | (BYTE *)in->authData.t.buffer); |
| 102 | |
| 103 | /* Add the sesson nonce */ |
| 104 | CryptUpdateDigest2B(&hashState, &session->nonceTPM.b); |
| 105 | |
| 106 | /* Complete digest */ |
| 107 | CryptCompleteHash2B(&hashState, &authHash.b); |
| 108 | |
| 109 | /* |
| 110 | * Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or |
| 111 | * TPM_RC_SIGNATURE error may be returned at this point. |
| 112 | */ |
| 113 | result = CryptVerifySignature(in->authObject, &authHash, &in->auth); |
| 114 | if (result != TPM_RC_SUCCESS) |
| 115 | return RcSafeAddToResult(result, RC_PolicySigned_auth); |
| 116 | } |
| 117 | |
| 118 | /* Internal Data Update */ |
| 119 | |
| 120 | /* Need the Name of the signing entity */ |
| 121 | entityName.t.size = EntityGetName(in->authObject, &entityName.t.name); |
| 122 | |
| 123 | /* |
| 124 | * Update policy with input policyRef and name of auth key |
| 125 | * These values are updated even if the session is a trial session |
| 126 | */ |
| 127 | PolicyFidoContextUpdate(TPM_CCE_PolicyFidoSigned, |
| 128 | &entityName, |
| 129 | in, |
| 130 | session); |
| 131 | |
| 132 | /* |
| 133 | * Command Output |
| 134 | * |
| 135 | * No output to generate. |
| 136 | */ |
| 137 | |
| 138 | return TPM_RC_SUCCESS; |
| 139 | } |