std::string Encrypt()

in azure-protected-vm-secrets/SecretsProvisioningSample/SecretsProvisioningSample.cpp [80:204]


std::string Encrypt(const char* data) {
    std::vector<unsigned char> secretData(data, data + strlen(data) + 1);
    std::vector<unsigned char> ciphertextData;
    std::vector<unsigned char> wrappedAesKey;
    std::vector<unsigned char> encryptedSecret, encryptedEcdhPrivate;
    std::vector<unsigned char> dataNonce, wrappingNonce;
    std::unique_ptr<Tss2Wrapper> tss2Wrapper;
    std::unique_ptr<AesWrapper> aesWrapper;
    std::unique_ptr<AesCreator> aesCreator;
    std::unique_ptr<AesChainingInfo>  aesChainingInfo;
    std::vector<unsigned char> wrappingKey, aesKey;
    std::vector<unsigned char> exportedPublicKeyData, exportedPrivateKeyData;
    std::vector<unsigned char> saltData = MakeRandomBytes(32);
    std::unique_ptr<JsonWebToken> jwt;
	std::string token;

    try {
        std::string infoString = GetSystemUuid();
        std::vector<unsigned char> infoData(infoString.begin(), infoString.end());

        // Generate ECDH key pair
#ifdef PLATFORM_UNIX
		std::unique_ptr<OsslECDiffieHellman> ecdhPrivate = std::make_unique<OsslECDiffieHellman>();
		std::unique_ptr<OsslECDiffieHellman> ecdhPublic = std::make_unique <OsslECDiffieHellman>();
#else
		std::unique_ptr<BcryptECDiffieHellman> ecdhPrivate = std::make_unique<BcryptECDiffieHellman>();
		std::unique_ptr<BcryptECDiffieHellman> ecdhPublic = std::make_unique<BcryptECDiffieHellman>();
#endif
        ecdhPrivate->GenerateKeyPair();
        ecdhPublic->GenerateKeyPair();
        exportedPublicKeyData = ecdhPublic->ExportSubjectPublicKeyInfo();
        exportedPrivateKeyData = ecdhPrivate->ExportPkcs8PrivateKey();

        // Derive shared secret
#ifdef PLATFORM_UNIX
        OsslHKDF hkdf = OsslHKDF(ecdhPrivate->DeriveSecret(*ecdhPublic));
#else
		BcryptHKDF hkdf = BcryptHKDF(ecdhPrivate->DeriveSecret(*ecdhPublic));
#endif
        aesKey = hkdf.DeriveKey(saltData, infoData, 32);
        if (aesKey.size() == 0) {
            std::cout << "Failed to derive key" << std::endl;
            return token;
        }
        std::cout << "Derived key size" << aesKey.size() << std::endl;

        // Prep AesWrapper
#ifdef PLATFORM_UNIX
		aesCreator = std::make_unique<OsslGcmCreator>();
#else
        aesCreator = std::make_unique<GcmCreator>();
#endif // PLATFORM_UNIX
        aesWrapper = aesCreator->CreateAesWrapper();

        // Encrypt the secret data
        aesWrapper->SetKey(aesKey);
        dataNonce = MakeRandomBytes(12);
		aesChainingInfo = aesWrapper->SetChainingInfo(dataNonce);
		encryptedSecret = aesWrapper->Encrypt(secretData, aesChainingInfo.get());
		if (encryptedSecret.size() == 0) {
			std::cout << "Failed to encrypt data" << std::endl;
			return token;
		}
		std::cout << "Encrypted data size" << encryptedSecret.size() << std::endl;

		// Encrypt the private key
		std::vector<unsigned char> wrappingKey = MakeRandomBytes(32);
		aesWrapper->SetKey(wrappingKey);
		wrappingNonce = MakeRandomBytes(12);
		aesChainingInfo = aesWrapper->SetChainingInfo(wrappingNonce);
		encryptedEcdhPrivate = aesWrapper->Encrypt(exportedPrivateKeyData, aesChainingInfo.get());
		if (encryptedSecret.size() == 0) {
			std::cout << "Failed to encrypt data" << std::endl;
			return token;
		}

		// Encrypt AES key with EK
		tss2Wrapper = std::make_unique <Tss2Wrapper>();
		printf("Generated EK\nPreparing to encrypt\n");
		wrappedAesKey = tss2Wrapper->Tss2RsaEncrypt(wrappingKey);
		if (wrappedAesKey.size() == 0) {
			std::cout << "Failed to wrap key" << std::endl;
			return token;
		}

	}
	catch (TpmError e) {
		std::cout << "Error in TPM " << e.getTPMError() << std::endl;
		return token;
	}
#ifndef PLATFORM_UNIX
	catch (BcryptError e) {
		std::cout << "Error in Bcrypt " << e.getErrorInfo() << std::endl;
		return token;
	}
#else
	catch (OsslError e) {
		std::cout << "Error in Ossl " << e.getErrorInfo() << std::endl;
		return token;
	}
#endif // !PLATFORM_UNIX
	catch (std::exception e) {
		std::cout << "Failed to encrypt data" << e.what() << std::endl;
		return token;
	}
	// Prepare jwt
	jwt = std::make_unique<JsonWebToken>();
	json header = {
		{"alg", "RS256"},
		{"typ", "JWT"}
	};
	jwt->SetHeader(header);
	json payload = {
		{"salt", encoders::base64_encode(saltData)},
		{"dataNonce", encoders::base64_encode(dataNonce)},
		{"keyNonce", encoders::base64_encode(wrappingNonce)},
		{"wrappedAesTransportKey", encoders::base64_encode(wrappedAesKey)},
		{"encryptedSecret", encoders::base64_encode(encryptedSecret)},
		{"encryptedGuestEcdhPrivateKey", encoders::base64_encode(encryptedEcdhPrivate)},
		{"ephemeralEcdhPublicKey", encoders::base64_encode(exportedPublicKeyData)}
	};
	jwt->SetPayload(payload);
	token = jwt->CreateToken();
	return token;
}