1 2 /* 3 * Licensed Materials - Property of IBM 4 * 5 * trousers - An open source TCG Software Stack 6 * 7 * (C) Copyright International Business Machines Corp. 2004-2007 8 * 9 */ 10 11 12 #include <stdlib.h> 13 #include <stdio.h> 14 #include <string.h> 15 16 #include "trousers/tss.h" 17 #include "trousers/trousers.h" 18 #include "trousers_types.h" 19 #include "spi_utils.h" 20 #include "capabilities.h" 21 #include "tsplog.h" 22 #include "obj.h" 23 #include "authsess.h" 24 25 26 TSS_RESULT 27 Tspi_Data_Seal(TSS_HENCDATA hEncData, /* in */ 28 TSS_HKEY hEncKey, /* in */ 29 UINT32 ulDataLength, /* in */ 30 BYTE * rgbDataToSeal, /* in */ 31 TSS_HPCRS hPcrComposite) /* in */ 32 { 33 TPM_DIGEST digest; 34 TSS_RESULT result; 35 TSS_HPOLICY hPolicy, hEncPolicy; 36 BYTE *encData = NULL; 37 BYTE *pcrData = NULL; 38 UINT32 encDataSize; 39 UINT32 pcrDataSize; 40 UINT32 pcrInfoType = TSS_PCRS_STRUCT_DEFAULT; 41 UINT32 sealOrdinal = TPM_ORD_Seal; 42 TCS_KEY_HANDLE tcsKeyHandle; 43 TSS_HCONTEXT tspContext; 44 Trspi_HashCtx hashCtx; 45 BYTE *sealData = NULL; 46 struct authsess *xsap = NULL; 47 #ifdef TSS_BUILD_SEALX 48 UINT32 protectMode; 49 #endif 50 51 if (rgbDataToSeal == NULL) 52 return TSPERR(TSS_E_BAD_PARAMETER); 53 54 if ((result = obj_encdata_get_tsp_context(hEncData, &tspContext))) 55 return result; 56 57 if ((result = obj_rsakey_get_policy(hEncKey, TSS_POLICY_USAGE, 58 &hPolicy, NULL))) 59 return result; 60 61 if ((result = obj_encdata_get_policy(hEncData, TSS_POLICY_USAGE, 62 &hEncPolicy))) 63 return result; 64 65 if ((result = obj_rsakey_get_tcs_handle(hEncKey, &tcsKeyHandle))) 66 return result; 67 68 #ifdef TSS_BUILD_SEALX 69 /* Get the TSS_TSPATTRIB_ENCDATASEAL_PROTECT_MODE attribute 70 to determine the seal function to invoke */ 71 if ((result = obj_encdata_get_seal_protect_mode(hEncData, &protectMode))) 72 return result; 73 74 if (protectMode == TSS_TSPATTRIB_ENCDATASEAL_NO_PROTECT) { 75 sealOrdinal = TPM_ORD_Seal; 76 pcrInfoType = 0; 77 } else if (protectMode == TSS_TSPATTRIB_ENCDATASEAL_PROTECT) { 78 sealOrdinal = TPM_ORD_Sealx; 79 pcrInfoType = TSS_PCRS_STRUCT_INFO_LONG; 80 } else 81 return TSPERR(TSS_E_INTERNAL_ERROR); 82 #endif 83 84 /* If PCR's are of interest */ 85 pcrDataSize = 0; 86 if (hPcrComposite) { 87 if ((result = obj_pcrs_create_info_type(hPcrComposite, &pcrInfoType, &pcrDataSize, 88 &pcrData))) 89 return result; 90 } 91 92 if ((result = authsess_xsap_init(tspContext, hEncKey, hEncData, TSS_AUTH_POLICY_REQUIRED, 93 sealOrdinal, TPM_ET_KEYHANDLE, &xsap))) 94 goto error; 95 96 #ifdef TSS_BUILD_SEALX 97 if (sealOrdinal == TPM_ORD_Seal) 98 sealData = rgbDataToSeal; 99 else { 100 if ((sealData = (BYTE *)calloc(1, ulDataLength)) == NULL) { 101 LogError("malloc of %u bytes failed", ulDataLength); 102 result = TSPERR(TSS_E_OUTOFMEMORY); 103 goto error; 104 } 105 106 if ((result = 107 ((TSS_RESULT (*)(PVOID, TSS_HKEY, TSS_HENCDATA, TSS_ALGORITHM_ID, 108 UINT32, BYTE *, BYTE *, BYTE *, BYTE *, UINT32, BYTE *, 109 BYTE *))xsap->cb_sealx.callback)(xsap->cb_sealx.appData, hEncKey, hEncData, 110 xsap->cb_sealx.alg, sizeof(TPM_NONCE), 111 xsap->auth.NonceEven.nonce, 112 xsap->auth.NonceOdd.nonce, 113 xsap->nonceEvenxSAP.nonce, 114 xsap->nonceOddxSAP.nonce, ulDataLength, 115 rgbDataToSeal, sealData))) 116 goto error; 117 } 118 #else 119 sealData = rgbDataToSeal; 120 #endif 121 122 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 123 result |= Trspi_Hash_UINT32(&hashCtx, sealOrdinal); 124 result |= Trspi_Hash_ENCAUTH(&hashCtx, xsap->encAuthUse.authdata); 125 result |= Trspi_Hash_UINT32(&hashCtx, pcrDataSize); 126 result |= Trspi_HashUpdate(&hashCtx, pcrDataSize, pcrData); 127 result |= Trspi_Hash_UINT32(&hashCtx, ulDataLength); 128 result |= Trspi_HashUpdate(&hashCtx, ulDataLength, sealData); 129 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) { 130 goto error; 131 } 132 133 if ((result = authsess_xsap_hmac(xsap, &digest))) 134 goto error; 135 136 #ifdef TSS_BUILD_SEALX 137 if (sealOrdinal == TPM_ORD_Seal) { 138 if ((result = TCS_API(tspContext)->Seal(tspContext, tcsKeyHandle, &xsap->encAuthUse, 139 pcrDataSize, pcrData, ulDataLength, 140 sealData, xsap->pAuth, &encDataSize, 141 &encData))) { 142 goto error; 143 } 144 } else if (sealOrdinal == TPM_ORD_Sealx) { 145 if ((result = TCS_API(tspContext)->Sealx(tspContext, tcsKeyHandle, &xsap->encAuthUse, 146 pcrDataSize, pcrData, ulDataLength, sealData, 147 xsap->pAuth, &encDataSize, &encData))) { 148 goto error; 149 } 150 } else { 151 result = TSPERR(TSS_E_INTERNAL_ERROR); 152 goto error; 153 } 154 #else 155 if ((result = TCS_API(tspContext)->Seal(tspContext, tcsKeyHandle, &xsap->encAuthUse, 156 pcrDataSize, pcrData, ulDataLength, sealData, 157 xsap->pAuth, &encDataSize, &encData))) 158 goto error; 159 #endif 160 161 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 162 result |= Trspi_Hash_UINT32(&hashCtx, result); 163 result |= Trspi_Hash_UINT32(&hashCtx, sealOrdinal); 164 result |= Trspi_HashUpdate(&hashCtx, encDataSize, encData); 165 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 166 goto error; 167 168 if ((result = authsess_xsap_verify(xsap, &digest))) 169 goto error; 170 171 /* Need to set the object with the blob and the pcr's */ 172 if ((result = obj_encdata_set_data(hEncData, encDataSize, encData))) 173 goto error; 174 175 if (pcrDataSize) 176 result = obj_encdata_set_pcr_info(hEncData, pcrInfoType, pcrData); 177 178 error: 179 authsess_free(xsap); 180 free(encData); 181 free(pcrData); 182 if (sealData != rgbDataToSeal) 183 free(sealData); 184 return result; 185 } 186 187 TSS_RESULT 188 Tspi_Data_Unseal(TSS_HENCDATA hEncData, /* in */ 189 TSS_HKEY hKey, /* in */ 190 UINT32 * pulUnsealedDataLength,/* out */ 191 BYTE ** prgbUnsealedData) /* out */ 192 { 193 UINT64 offset; 194 TPM_AUTH privAuth2; 195 TPM_DIGEST digest; 196 TPM_NONCE authLastNonceEven; 197 TSS_RESULT result; 198 TSS_HPOLICY hPolicy, hEncPolicy; 199 TCS_KEY_HANDLE tcsKeyHandle; 200 TSS_HCONTEXT tspContext; 201 UINT32 ulDataLen, unSealedDataLen; 202 BYTE *data = NULL, *unSealedData = NULL, *maskedData; 203 UINT16 mask; 204 Trspi_HashCtx hashCtx; 205 struct authsess *xsap = NULL; 206 207 if (pulUnsealedDataLength == NULL || prgbUnsealedData == NULL) 208 return TSPERR(TSS_E_BAD_PARAMETER); 209 210 if ((result = obj_encdata_get_tsp_context(hEncData, &tspContext))) 211 return result; 212 213 if ((result = obj_rsakey_get_policy(hKey, TSS_POLICY_USAGE, &hPolicy, NULL))) 214 return result; 215 216 if ((result = obj_encdata_get_policy(hEncData, TSS_POLICY_USAGE, &hEncPolicy))) 217 return result; 218 219 if ((result = obj_encdata_get_data(hEncData, &ulDataLen, &data))) 220 return result == (TSS_E_INVALID_OBJ_ACCESS | TSS_LAYER_TSP) ? 221 TSPERR(TSS_E_ENC_NO_DATA) : 222 result; 223 224 offset = 0; 225 Trspi_UnloadBlob_UINT16(&offset, &mask, data); 226 if (mask == TPM_TAG_STORED_DATA12) { 227 /* The second UINT16 in a TPM_STORED_DATA12 is the entity type. If its non-zero 228 * then we must unmask the unsealed data after it returns from the TCS */ 229 Trspi_UnloadBlob_UINT16(&offset, &mask, data); 230 } else 231 mask = 0; 232 233 if ((result = obj_rsakey_get_tcs_handle(hKey, &tcsKeyHandle))) 234 goto error; 235 236 if ((result = authsess_xsap_init(tspContext, hKey, hEncData, TSS_AUTH_POLICY_REQUIRED, 237 TPM_ORD_Unseal, TPM_ET_KEYHANDLE, &xsap))) 238 goto error; 239 240 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 241 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Unseal); 242 result |= Trspi_HashUpdate(&hashCtx, ulDataLen, data); 243 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) 244 goto error; 245 246 if ((result = authsess_xsap_hmac(xsap, &digest))) 247 goto error; 248 249 if ((result = secret_PerformAuth_OIAP(hEncData, TPM_ORD_Unseal, hEncPolicy, FALSE, &digest, 250 &privAuth2))) 251 goto error; 252 253 if (mask) { 254 /* save off last nonce even to pass to sealx callback */ 255 memcpy(authLastNonceEven.nonce, xsap->auth.NonceEven.nonce, sizeof(TPM_NONCE)); 256 } 257 258 if ((result = TCS_API(tspContext)->Unseal(tspContext, tcsKeyHandle, ulDataLen, data, 259 xsap->pAuth, &privAuth2, &unSealedDataLen, 260 &unSealedData))) 261 goto error; 262 263 result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); 264 result |= Trspi_Hash_UINT32(&hashCtx, TSS_SUCCESS); 265 result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_Unseal); 266 result |= Trspi_Hash_UINT32(&hashCtx, unSealedDataLen); 267 result |= Trspi_HashUpdate(&hashCtx, unSealedDataLen, unSealedData); 268 if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) { 269 free(unSealedData); 270 goto error; 271 } 272 273 if ((result = authsess_xsap_verify(xsap, &digest))) { 274 free(unSealedData); 275 goto error; 276 } 277 278 if ((result = obj_policy_validate_auth_oiap(hEncPolicy, &digest, &privAuth2))) { 279 free(unSealedData); 280 goto error; 281 } 282 283 /* If the data is masked, use the callback set up in authsess_xsap_init */ 284 if (mask) { 285 maskedData = unSealedData; 286 287 if ((unSealedData = calloc_tspi(tspContext, unSealedDataLen)) == NULL) { 288 free(maskedData); 289 LogError("malloc of %u bytes failed", unSealedDataLen); 290 result = TSPERR(TSS_E_OUTOFMEMORY); 291 goto error; 292 } 293 294 /* XXX pass in out saved-off authLastNonceEven. This conflicts with the 295 * description of the rgbNonceEven parameter in the spec, but without it, its not 296 * possible to compute the MGF1 key */ 297 if ((result = 298 ((TSS_RESULT (*)(PVOID, TSS_HKEY, TSS_HENCDATA, TSS_ALGORITHM_ID, 299 UINT32, BYTE *, BYTE *, BYTE *, BYTE *, UINT32, BYTE *, 300 BYTE *))xsap->cb_sealx.callback)(xsap->cb_sealx.appData, hKey, hEncData, 301 xsap->cb_sealx.alg, sizeof(TPM_NONCE), 302 authLastNonceEven.nonce, 303 xsap->auth.NonceOdd.nonce, 304 xsap->nonceEvenxSAP.nonce, 305 xsap->nonceOddxSAP.nonce, 306 unSealedDataLen, maskedData, 307 unSealedData))) { 308 free(maskedData); 309 goto error; 310 } 311 312 free(maskedData); 313 } else { 314 if ((result = __tspi_add_mem_entry(tspContext, unSealedData))) 315 goto error; 316 } 317 318 *pulUnsealedDataLength = unSealedDataLen; 319 *prgbUnsealedData = unSealedData; 320 321 error: 322 authsess_free(xsap); 323 if (data) 324 free_tspi(tspContext, data); 325 326 return result; 327 } 328