bool CRegProtocol::ValidateMac(BufferObj &data, uint8 *hmac, BufferObj &key) { uint8 dataMac[BUF_SIZE_256_BITS]; //First calculate the hmac of the data if(HMAC(EVP_sha256(), key.GetBuf(), SIZE_256_BITS, data.GetBuf(), data.Length(), dataMac, NULL) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: HMAC failed\n")); if (TUTRACELEVEL & TUVERBOSE && g_verbose) { // for debugging purposes printf("Computed HMAC (note: only first 64 bits will be compared)\n"); for (int i = 0; i < BUF_SIZE_256_BITS; i++) { printf("%2x ",dataMac[i]); } printf("\nHMAC from Authenticator(should match first 64 bits of computed HMAC)\n"); for (int i = 0; i < 8; i++) { printf("%2x ",hmac[i]); } printf("\nKey is:\n"); for (int i = 0; i < 8; i++) { printf("%2x ",(key.GetBuf())[i]); } printf("\n"); } throw RPROT_ERR_CRYPTO; } else { if (TUTRACELEVEL & TUVERBOSE && g_verbose) { // for debugging purposes printf("Computed HMAC (note: only first 64 bits will be compared)\n"); for (int i = 0; i < BUF_SIZE_256_BITS; i++) { printf("%2x ",dataMac[i]); } printf("\nHMAC from Authenticator(should match first 64 bits of computed HMAC)\n"); for (int i = 0; i < 8; i++) { printf("%2x ",hmac[i]); } printf("\nKey is:\n"); for (int i = 0; i < BUF_SIZE_256_BITS; i++) { printf("%2x ",(key.GetBuf())[i]); } printf("\n"); } } //next, compare it against the received hmac TUTRACE((TUTRACE_INFO, "RPROTO: Verifying the first 64 bits of the generated HMAC\n")); if(memcmp(dataMac, hmac, SIZE_64_BITS) != 0) { printf("RPROTO: HMAC results don't match\n"); return false; } TUTRACE((TUTRACE_VERBOSE, "RPROTO: HMAC results match\n")); return true; }
void CTlvEsM8Sta::write(BufferObj &theBuf, BufferObj &authKey, bool isWirelessWPS) { LPLISTITR itr; CTlvCredential *pCredential; //there should be at least one credential TLV if(isWirelessWPS && 0 == ListGetCount(credential)) throw RPROT_ERR_REQD_TLV_MISSING; try { if (isWirelessWPS) { // skip including Credential if not in wireless WPS mode if(!(itr = ListItrCreate(credential))) throw WSC_ERR_OUTOFMEMORY; while((pCredential = (CTlvCredential *)ListItrGetNext(itr))) { pCredential->write(theBuf); } } //write the optional new password and device password ID if(new_pwd.Length()) { new_pwd.Write(theBuf); pwdId.Write(theBuf); } //calculate the hmac and append the TLV to the buffer uint8 hmac[SIZE_256_BITS]; if(HMAC(EVP_sha256(), authKey.GetBuf(), SIZE_256_BITS, theBuf.GetBuf(), theBuf.Length(), hmac, NULL) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: Error generating HMAC\n")); throw RPROT_ERR_CRYPTO; } CTlvAuthenticator( WSC_ID_KEY_WRAP_AUTH, theBuf, hmac, SIZE_64_BITS); if (isWirelessWPS) { // itr is only valid if in wireless WPS mode ListItrDelete(itr); } } catch(...) { if(itr) ListItrDelete(itr); } }
void CRegProtocol::GenerateSHA256Hash(BufferObj &inBuf, BufferObj &outBuf) { uint8 Hash[SIZE_256_BITS]; if(SHA256(inBuf.GetBuf(), inBuf.Length(), Hash) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: SHA256 calculation failed\n")); throw RPROT_ERR_CRYPTO; } outBuf.Append(SIZE_256_BITS, Hash); }//GenerateHash
void CRegProtocol::DeriveKey(BufferObj &KDK, BufferObj &prsnlString, uint32 keyBits, BufferObj &key) { uint32 i = 0, iterations = 0; BufferObj input, output; uint8 hmac[SIZE_256_BITS]; uint32 hmacLen = 0; uint8 *inPtr; uint32 temp; TUTRACE((TUTRACE_INFO, "RPROTO: Deriving a key of %d bits\n", keyBits)); iterations = ((keyBits/8) + PRF_DIGEST_SIZE - 1)/PRF_DIGEST_SIZE; //Prepare the input buffer. During the iterations, we need only replace the //value of i at the start of the buffer. temp = WscHtonl(i); input.Append(SIZE_4_BYTES, (uint8 *)&temp); input.Append(prsnlString.Length(), prsnlString.GetBuf()); temp = WscHtonl(keyBits); input.Append(SIZE_4_BYTES, (uint8 *)&temp); inPtr = input.GetBuf(); for(i = 0; i < iterations; i++) { //Set the current value of i at the start of the input buffer *(uint32 *)inPtr = WscHtonl(i+1); //i should start at 1 if(HMAC(EVP_sha256(), KDK.GetBuf(), SIZE_256_BITS, input.GetBuf(), input.Length(), hmac, &hmacLen) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: HMAC failed\n")); throw RPROT_ERR_CRYPTO; } output.Append(hmacLen, hmac); } //Sanity check if(keyBits/8 > output.Length()) { TUTRACE((TUTRACE_ERR, "RPROTO: Key derivation generated less bits " "than asked\n")); throw RPROT_ERR_CRYPTO; } //We now have at least the number of key bits requested. //Return only the number of bits asked for. Discard the excess. key.Append(keyBits/8, output.GetBuf()); }
void CTlvEsNonce::write(BufferObj &theBuf, BufferObj &authKey) { nonce.Write(theBuf); //calculate the hmac and append the TLV to the buffer uint8 hmac[SIZE_256_BITS]; if(HMAC(EVP_sha256(), authKey.GetBuf(), SIZE_256_BITS, theBuf.GetBuf(), theBuf.Length(), hmac, NULL) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: Error generating HMAC\n")); throw RPROT_ERR_CRYPTO; } CTlvAuthenticator( WSC_ID_KEY_WRAP_AUTH, theBuf, hmac, SIZE_64_BITS); //Only the first 64 bits are sent }
int WPSRegistrar::ProcessDone() { uint32 err; err = g_regProtocol.ProcessMessageDone(&m_regInfo, m_msgBuffer ); if(WSC_SUCCESS != err) { return err_process_Done; } printf("\n***** Successfully processed Message Done\n"); if (m_regInfo.p_enrolleeInfo) { WPSDeviceWasAuthenticated(* ((GUID*) & (m_regInfo.p_enrolleeInfo->uuid))); } //****** Derivation of UPnP Protected Setup AuthKey and KeyWrapKey ****** //1. declare and initialize the appropriate buffer objects BufferObj kdkBuf(m_regInfo.emsk.GetBuf(), SIZE_256_BITS); BufferObj pString((uint8 *)UPNP_PERSONALIZATION_STRING, strlen(UPNP_PERSONALIZATION_STRING)); BufferObj keys; //2. call the key derivation function g_regProtocol.DeriveKey(kdkBuf, pString, 256 + 128, keys); //3. split the key into the component keys and store them keys.Rewind(keys.Length()); m_regInfo.UPnPPSauthKey.Reset(); m_regInfo.UPnPPSkeyWrapKey.Reset(); m_regInfo.UPnPPSauthKey.Append(SIZE_256_BITS, keys.Pos()); keys.Advance(SIZE_256_BITS); m_regInfo.UPnPPSkeyWrapKey.Append(SIZE_128_BITS, keys.Pos()); // **** End of key derivation code return init; }
bool CRegProtocol::ValidateKeyWrapAuth(BufferObj &data, uint8 *hmac, BufferObj &key) { //Same as ValidateMac, except only the first 64 bits are validated uint8 dataMac[BUF_SIZE_256_BITS]; //First calculate the hmac of the data if(HMAC(EVP_sha256(), key.GetBuf(), SIZE_256_BITS, data.GetBuf(), data.Length(), dataMac, NULL) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: HMAC failed\n")); throw RPROT_ERR_CRYPTO; } //next, compare it against the received hmac if(memcmp(dataMac, hmac, SIZE_64_BITS) != 0) { TUTRACE((TUTRACE_ERR, "RPROTO: HMAC results don't match\n")); return false; } return true; }
void CTlvEsM8Ap::write(BufferObj &theBuf, BufferObj &authKey) { LPLISTITR indexItr, keyItr; CTlvNwKeyIndex *keyIndex; CTlvNwKey *key; try { if(!(indexItr = ListItrCreate(nwKeyIndex))) throw WSC_ERR_OUTOFMEMORY; if(!(keyItr = ListItrCreate(nwKey))) throw WSC_ERR_OUTOFMEMORY; //nwIndex is an optional field if(nwIndex.Length()) nwIndex.Write(theBuf); ssid.Write(theBuf); authType.Write(theBuf); encrType.Write(theBuf); //write the network index and network key to the buffer if(ListGetCount(nwKeyIndex) == 0) { //Condition1. There is no key index, so there can only be 1 nw key if(!(key = (CTlvNwKey *) ListItrGetNext(keyItr))) throw WSC_ERR_OUTOFMEMORY; key->Write(theBuf); } else { //Condition2. There are multiple network keys. while((keyIndex= (CTlvNwKeyIndex *) ListItrGetNext(indexItr))) { if(!(key = (CTlvNwKey *) ListItrGetNext(keyItr))) throw WSC_ERR_OUTOFMEMORY; keyIndex->Write(theBuf); key->Write(theBuf); }//while }//else //write the mac address macAddr.Write(theBuf); //write the optional new password and device password ID if(new_pwd.Length()) { new_pwd.Write(theBuf); pwdId.Write(theBuf); } //calculate the hmac and append the TLV to the buffer uint8 hmac[SIZE_256_BITS]; if(HMAC(EVP_sha256(), authKey.GetBuf(), SIZE_256_BITS, theBuf.GetBuf(), theBuf.Length(), hmac, NULL) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: Error generating HMAC\n")); throw RPROT_ERR_CRYPTO; } CTlvAuthenticator( WSC_ID_KEY_WRAP_AUTH, theBuf, hmac, SIZE_64_BITS); ListItrDelete(indexItr); ListItrDelete(keyItr); } catch(...) { if(indexItr) ListItrDelete(indexItr); if(keyItr) ListItrDelete(keyItr); throw; } }
void CRegProtocol::DecryptData(BufferObj &cipherText, BufferObj &iv, BufferObj &encrKey, BufferObj &authKey, BufferObj &plainText) { EVP_CIPHER_CTX ctx; if(0 == EVP_DecryptInit(&ctx, EVP_aes_128_cbc(), encrKey.GetBuf(), iv.GetBuf())) { TUTRACE((TUTRACE_ERR, "RPROTO: DecryptInit failed\n")); throw RPROT_ERR_CRYPTO; } BufferObj buf; int bufLen = 1024; uint8 outBuf[1024]; int outLen, currentLength; //block size = 1024 bytes - 128 bits, //leave 128 bits at the end to accommodate any possible padding //and avoid a buffer overflow int blockSize = bufLen - SIZE_128_BITS; int length = cipherText.Length(); uint8 *bufPtr = cipherText.GetBuf(); while(length) { if(length > blockSize) currentLength = blockSize; else currentLength = length; if(0 == EVP_DecryptUpdate(&ctx, outBuf, &outLen, bufPtr, currentLength)) { TUTRACE((TUTRACE_ERR, "RPROTO: DecryptUpdate failed\n")); throw RPROT_ERR_CRYPTO; } buf.Append(outLen, outBuf); bufPtr += currentLength; length -= currentLength; } if(0 == EVP_DecryptFinal(&ctx, outBuf, &outLen)) { TUTRACE((TUTRACE_ERR, "RPROTO: DecryptFinal failed\n")); throw RPROT_ERR_CRYPTO; } buf.Append(outLen, outBuf); //Validate the mac at the end of the decrypted buffer //uint8 *mac = buf.GetBuf()+(buf.Length()-SIZE_256_BITS);//get the last 256 bits //if(0 == ValidateMac(BufferObj(buf.GetBuf(), buf.Length()-SIZE_256_BITS), mac, authKey)) //{ // TUTRACE((TUTRACE_ERR, "RPROTO: Mac validation failed\n")); // throw RPROT_ERR_INVALID_VALUE; //} //plainText.Append(buf.Length()-SIZE_256_BITS, buf.GetBuf()); plainText.Append(buf.Length(), buf.GetBuf()); plainText.Rewind(plainText.Length()); }
void CRegProtocol::EncryptData(BufferObj &plainText, BufferObj &encrKey, BufferObj &authKey, BufferObj &cipherText, BufferObj &iv) { BufferObj buf; uint8 ivBuf[SIZE_128_BITS]; if(0 == plainText.Length()) throw WSC_ERR_INVALID_PARAMETERS; //Generate a random iv RAND_bytes(ivBuf, SIZE_128_BITS); iv.Reset(); iv.Append(SIZE_128_BITS, ivBuf); //Now encrypt the plaintext and mac using the encryption key and IV. buf.Append(plainText.Length(), plainText.GetBuf()); EVP_CIPHER_CTX ctx; if(0 == EVP_EncryptInit(&ctx, EVP_aes_128_cbc(), encrKey.GetBuf(), ivBuf)) { TUTRACE((TUTRACE_ERR, "RPROTO: EncryptInit failed\n")); throw RPROT_ERR_CRYPTO; } int bufLen = 1024; uint8 outBuf[1024]; int outLen, currentLength; //block size = 1024 bytes - 128 bits, //leave 128 bits at the end to accommodate any possible padding //and avoid a buffer overflow int blockSize = bufLen - SIZE_128_BITS; int length = buf.Length(); uint8 *bufPtr = buf.GetBuf(); while(length) { if(length > blockSize) currentLength = blockSize; else currentLength = length; if(0 == EVP_EncryptUpdate(&ctx, outBuf, &outLen, bufPtr, currentLength)) { TUTRACE((TUTRACE_ERR, "RPROTO: EncryptUpdate failed\n")); throw RPROT_ERR_CRYPTO; } cipherText.Append(outLen, outBuf); bufPtr += currentLength; length -= currentLength; } if(0 == EVP_EncryptFinal(&ctx, outBuf, &outLen)) { TUTRACE((TUTRACE_ERR, "RPROTO: EncryptFinal failed\n")); throw RPROT_ERR_CRYPTO; } cipherText.Append(outLen, outBuf); }