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 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); }
uint32 CRegProtocol::GenerateDHKeyPair(DH **DHKeyPair, BufferObj &pubKey) { uint8 temp[SIZE_PUB_KEY]; try { //1. Initialize the DH structure *DHKeyPair = DH_new(); if(*DHKeyPair == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: DH_new failed\n")); throw RPROT_ERR_CRYPTO; } (*DHKeyPair)->p = BN_new(); (*DHKeyPair)->g = BN_new(); //2. load the value of P if(BN_bin2bn(DH_P_VALUE, BUF_SIZE_1536_BITS, (*DHKeyPair)->p)==NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_bin2bn P: %s", ERR_error_string(ERR_get_error(), NULL))); throw RPROT_ERR_CRYPTO; } //3. load the value of G uint32 g = WscHtonl(DH_G_VALUE); if(BN_bin2bn((uint8 *)&g, 4, (*DHKeyPair)->g)==NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_bin2bn G: %s", ERR_error_string(ERR_get_error(), NULL))); throw RPROT_ERR_CRYPTO; } //4. generate the DH key if(DH_generate_key(*DHKeyPair) == 0) { TUTRACE((TUTRACE_ERR, "RPROTO: DH_generate_key: %s", ERR_error_string(ERR_get_error(), NULL))); throw RPROT_ERR_CRYPTO; } //5. extract the DH public key int len = BN_bn2bin((*DHKeyPair)->pub_key, temp); if(0 == len) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_bn2bin: %s", ERR_error_string(ERR_get_error(), NULL))); throw RPROT_ERR_CRYPTO; } pubKey.Append(SIZE_PUB_KEY, temp); return WSC_SUCCESS; } catch(uint32 err) { return err; } catch(...) { return WSC_ERR_SYSTEM; } }//GenerateDHKeyPair