@ -88,7 +88,7 @@ static bool checkSize(const std::string& kind, size_t actual, size_t expected) {
return true ;
}
static std : : string hashWithPrefix( char const * prefix , const std : : string & tohash ) {
static void hashWithPrefix( char const * prefix , const std : : string & tohash , std : : string * res ) {
SHA512_CTX c ;
SHA512_Init ( & c ) ;
@ -99,9 +99,8 @@ static std::string hashWithPrefix(char const* prefix, const std::string& tohash)
hashingPrefix . resize ( SHA512_CBLOCK ) ;
SHA512_Update ( & c , hashingPrefix . data ( ) , hashingPrefix . size ( ) ) ;
SHA512_Update ( & c , tohash . data ( ) , tohash . size ( ) ) ;
std : : string res ( SHA512_DIGEST_LENGTH , ' \0 ' ) ;
SHA512_Final ( reinterpret_cast < uint8_t * > ( & res [ 0 ] ) , & c ) ;
return res ;
res - > assign ( SHA512_DIGEST_LENGTH , ' \0 ' ) ;
SHA512_Final ( reinterpret_cast < uint8_t * > ( & ( * res ) [ 0 ] ) , & c ) ;
}
static bool generateKeymasterKey ( Keymaster & keymaster , const KeyAuthentication & auth ,
@ -160,6 +159,30 @@ static bool writeStringToFile(const std::string& payload, const std::string& fil
return true ;
}
static bool readRandomBytesOrLog ( size_t count , std : : string * out ) {
auto status = ReadRandomBytes ( count , * out ) ;
if ( status ! = OK ) {
LOG ( ERROR ) < < " Random read failed with status: " < < status ;
return false ;
}
return true ;
}
bool createSecdiscardable ( const std : : string & filename , std : : string * hash ) {
std : : string secdiscardable ;
if ( ! readRandomBytesOrLog ( SECDISCARDABLE_BYTES , & secdiscardable ) ) return false ;
if ( ! writeStringToFile ( secdiscardable , filename ) ) return false ;
hashWithPrefix ( kHashPrefix_secdiscardable , secdiscardable , hash ) ;
return true ;
}
bool readSecdiscardable ( const std : : string & filename , std : : string * hash ) {
std : : string secdiscardable ;
if ( ! readFileToString ( filename , & secdiscardable ) ) return false ;
hashWithPrefix ( kHashPrefix_secdiscardable , secdiscardable , hash ) ;
return true ;
}
static KeymasterOperation begin ( Keymaster & keymaster , const std : : string & dir ,
KeyPurpose purpose ,
const AuthorizationSet & keyParams ,
@ -283,20 +306,11 @@ static bool stretchSecret(const std::string& stretching, const std::string& secr
}
static bool generateAppId ( const KeyAuthentication & auth , const std : : string & stretching ,
const std : : string & salt , const std : : string & secdiscardable ,
const std : : string & salt , const std : : string & secdiscardable _hash ,
std : : string * appId ) {
std : : string stretched ;
if ( ! stretchSecret ( stretching , auth . secret , salt , & stretched ) ) return false ;
* appId = hashWithPrefix ( kHashPrefix_secdiscardable , secdiscardable ) + stretched ;
return true ;
}
static bool readRandomBytesOrLog ( size_t count , std : : string * out ) {
auto status = ReadRandomBytes ( count , * out ) ;
if ( status ! = OK ) {
LOG ( ERROR ) < < " Random read failed with status: " < < status ;
return false ;
}
* appId = secdiscardable_hash + stretched ;
return true ;
}
@ -306,7 +320,8 @@ static void logOpensslError() {
static bool encryptWithoutKeymaster ( const std : : string & preKey ,
const KeyBuffer & plaintext , std : : string * ciphertext ) {
auto key = hashWithPrefix ( kHashPrefix_keygen , preKey ) ;
std : : string key ;
hashWithPrefix ( kHashPrefix_keygen , preKey , & key ) ;
key . resize ( AES_KEY_BYTES ) ;
if ( ! readRandomBytesOrLog ( GCM_NONCE_BYTES , ciphertext ) ) return false ;
auto ctx = std : : unique_ptr < EVP_CIPHER_CTX , decltype ( & : : EVP_CIPHER_CTX_free ) > (
@ -356,7 +371,8 @@ static bool decryptWithoutKeymaster(const std::string& preKey,
LOG ( ERROR ) < < " GCM ciphertext too small: " < < ciphertext . size ( ) ;
return false ;
}
auto key = hashWithPrefix ( kHashPrefix_keygen , preKey ) ;
std : : string key ;
hashWithPrefix ( kHashPrefix_keygen , preKey , & key ) ;
key . resize ( AES_KEY_BYTES ) ;
auto ctx = std : : unique_ptr < EVP_CIPHER_CTX , decltype ( & : : EVP_CIPHER_CTX_free ) > (
EVP_CIPHER_CTX_new ( ) , EVP_CIPHER_CTX_free ) ;
@ -410,9 +426,8 @@ bool storeKey(const std::string& dir, const KeyAuthentication& auth, const KeyBu
return false ;
}
if ( ! writeStringToFile ( kCurrentVersion , dir + " / " + kFn_version ) ) return false ;
std : : string secdiscardable ;
if ( ! readRandomBytesOrLog ( SECDISCARDABLE_BYTES , & secdiscardable ) ) return false ;
if ( ! writeStringToFile ( secdiscardable , dir + " / " + kFn_secdiscardable ) ) return false ;
std : : string secdiscardable_hash ;
if ( ! createSecdiscardable ( dir + " / " + kFn_secdiscardable , & secdiscardable_hash ) ) return false ;
std : : string stretching = getStretching ( auth ) ;
if ( ! writeStringToFile ( stretching , dir + " / " + kFn_stretching ) ) return false ;
std : : string salt ;
@ -424,7 +439,7 @@ bool storeKey(const std::string& dir, const KeyAuthentication& auth, const KeyBu
if ( ! writeStringToFile ( salt , dir + " / " + kFn_salt ) ) return false ;
}
std : : string appId ;
if ( ! generateAppId ( auth , stretching , salt , secdiscardable , & appId ) ) return false ;
if ( ! generateAppId ( auth , stretching , salt , secdiscardable _hash , & appId ) ) return false ;
std : : string encryptedKey ;
if ( auth . usesKeymaster ( ) ) {
Keymaster keymaster ;
@ -467,8 +482,8 @@ bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffe
LOG ( ERROR ) < < " Version mismatch, expected " < < kCurrentVersion < < " got " < < version ;
return false ;
}
std : : string secdiscardable ;
if ( ! read FileToString ( dir + " / " + kFn_secdiscardable , & secdiscardable ) ) return false ;
std : : string secdiscardable _hash ;
if ( ! read Secdiscardable ( dir + " / " + kFn_secdiscardable , & secdiscardable _hash ) ) return false ;
std : : string stretching ;
if ( ! readFileToString ( dir + " / " + kFn_stretching , & stretching ) ) return false ;
std : : string salt ;
@ -476,7 +491,7 @@ bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffe
if ( ! readFileToString ( dir + " / " + kFn_salt , & salt ) ) return false ;
}
std : : string appId ;
if ( ! generateAppId ( auth , stretching , salt , secdiscardable , & appId ) ) return false ;
if ( ! generateAppId ( auth , stretching , salt , secdiscardable _hash , & appId ) ) return false ;
std : : string encryptedMessage ;
if ( ! readFileToString ( dir + " / " + kFn_encrypted_key , & encryptedMessage ) ) return false ;
if ( auth . usesKeymaster ( ) ) {