| 964 | } |
| 965 | |
| 966 | LocalEncryptedLeaseSet2::LocalEncryptedLeaseSet2 (std::shared_ptr<const LocalLeaseSet2> ls, const i2p::data::PrivateKeys& keys, |
| 967 | int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys): |
| 968 | LocalLeaseSet2 (ls->GetIdentity ()), m_InnerLeaseSet (ls) |
| 969 | { |
| 970 | size_t lenInnerPlaintext = ls->GetBufferLen () + 1, lenOuterPlaintext = lenInnerPlaintext + 32 + 1; |
| 971 | uint8_t layer1Flags = 0; |
| 972 | if (authKeys) |
| 973 | { |
| 974 | if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_DH) layer1Flags |= 0x01; // DH, authentication scheme 0, auth bit 1 |
| 975 | else if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_PSK) layer1Flags |= 0x03; // PSK, authentication scheme 1, auth bit 1 |
| 976 | if (layer1Flags) |
| 977 | lenOuterPlaintext += 32 + 2 + authKeys->size ()*40; // auth data len |
| 978 | } |
| 979 | size_t lenOuterCiphertext = lenOuterPlaintext + 32; |
| 980 | |
| 981 | m_BufferLen = 2/*blinded sig type*/ + 32/*blinded pub key*/ + 4/*published*/ + 2/*expires*/ + 2/*flags*/ + 2/*lenOuterCiphertext*/ + lenOuterCiphertext + 64/*signature*/; |
| 982 | m_Buffer = new uint8_t[m_BufferLen + 1]; |
| 983 | m_Buffer[0] = NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; |
| 984 | BlindedPublicKey blindedKey (ls->GetIdentity ()); |
| 985 | auto timestamp = i2p::util::GetSecondsSinceEpoch (); |
| 986 | char date[9]; |
| 987 | i2p::util::GetDateString (timestamp, date); |
| 988 | uint8_t blindedPriv[64], blindedPub[128]; // 64 and 128 max |
| 989 | size_t publicKeyLen = blindedKey.BlindPrivateKey (keys.GetSigningPrivateKey (), date, blindedPriv, blindedPub); |
| 990 | std::unique_ptr<i2p::crypto::Signer> blindedSigner (i2p::data::PrivateKeys::CreateSigner (blindedKey.GetBlindedSigType (), blindedPriv)); |
| 991 | if (!blindedSigner) |
| 992 | { |
| 993 | LogPrint (eLogError, "LeaseSet2: Can't create blinded signer for signature type ", blindedKey.GetSigType ()); |
| 994 | return; |
| 995 | } |
| 996 | auto offset = 1; |
| 997 | htobe16buf (m_Buffer + offset, blindedKey.GetBlindedSigType ()); offset += 2; // Blinded Public Key Sig Type |
| 998 | memcpy (m_Buffer + offset, blindedPub, publicKeyLen); offset += publicKeyLen; // Blinded Public Key |
| 999 | htobe32buf (m_Buffer + offset, timestamp); offset += 4; // published timestamp (seconds) |
| 1000 | auto nextMidnight = (timestamp/86400LL + 1)*86400LL; // 86400 = 24*3600 seconds |
| 1001 | auto expirationTime = ls->GetExpirationTime ()/1000LL; |
| 1002 | if (expirationTime > nextMidnight) expirationTime = nextMidnight; |
| 1003 | SetExpirationTime (expirationTime*1000LL); |
| 1004 | htobe16buf (m_Buffer + offset, expirationTime > timestamp ? expirationTime - timestamp : 0); offset += 2; // expires |
| 1005 | uint16_t flags = 0; |
| 1006 | htobe16buf (m_Buffer + offset, flags); offset += 2; // flags |
| 1007 | htobe16buf (m_Buffer + offset, lenOuterCiphertext); offset += 2; // lenOuterCiphertext |
| 1008 | // outerChipherText |
| 1009 | // Layer 1 |
| 1010 | uint8_t subcredential[36]; |
| 1011 | blindedKey.GetSubcredential (blindedPub, 32, subcredential); |
| 1012 | htobe32buf (subcredential + 32, timestamp); // outerInput = subcredential || publishedTimestamp |
| 1013 | // keys = HKDF(outerSalt, outerInput, "ELS2_L1K", 44) |
| 1014 | uint8_t keys1[64]; // 44 bytes actual data |
| 1015 | RAND_bytes (m_Buffer + offset, 32); // outerSalt = CSRNG(32) |
| 1016 | i2p::crypto::HKDF (m_Buffer + offset, subcredential, 36, "ELS2_L1K", keys1); |
| 1017 | offset += 32; // outerSalt |
| 1018 | uint8_t * outerPlainText = m_Buffer + offset; |
| 1019 | m_Buffer[offset] = layer1Flags; offset++; // layer 1 flags |
| 1020 | // auth data |
| 1021 | uint8_t innerInput[68]; // authCookie || subcredential || publishedTimestamp |
| 1022 | if (layer1Flags) |
| 1023 | { |
nothing calls this directly
no test coverage detected