struct CryptoAuth* CryptoAuth_new(struct Allocator* allocator, const uint8_t* privateKey, struct event_base* eventBase, struct Log* logger) { struct CryptoAuth_pvt* ca = allocator->calloc(sizeof(struct CryptoAuth_pvt), 1, allocator); ca->allocator = allocator; ca->passwords = allocator->calloc(sizeof(struct CryptoAuth_Auth), 256, allocator); ca->passwordCount = 0; ca->passwordCapacity = 256; ca->eventBase = eventBase; ca->logger = logger; ca->pub.resetAfterInactivitySeconds = CryptoAuth_DEFAULT_RESET_AFTER_INACTIVITY_SECONDS; if (privateKey != NULL) { Bits_memcpyConst(ca->privateKey, privateKey, 32); crypto_scalarmult_curve25519_base(ca->pub.publicKey, ca->privateKey); } else { crypto_box_curve25519xsalsa20poly1305_keypair(ca->pub.publicKey, ca->privateKey); } #ifdef Log_KEYS uint8_t publicKeyHex[65]; printHexKey(publicKeyHex, ca->pub.publicKey); uint8_t privateKeyHex[65]; printHexKey(privateKeyHex, ca->privateKey); Log_keys(logger, "Initialized CryptoAuth:\n myPrivateKey=%s\n myPublicKey=%s\n", privateKeyHex, publicKeyHex); #endif return &ca->pub; }
void generateKey(dpn_pubkey* pk, dpn_seckey* sk) { dpn_pubkey genpk; dpn_seckey gensk; while (!isPublicKeyValid(genpk)) { crypto_box_curve25519xsalsa20poly1305_keypair( (unsigned char*) &genpk, (unsigned char*) &gensk ); } memcpy(pk, genpk, sizeof(dpn_pubkey)); memcpy(sk, gensk, sizeof(dpn_seckey)); }
int main(int argc, char **argv) { global_urandom_fd = open("/dev/urandom", O_RDONLY); if (global_urandom_fd < 0) { perror("Opening /dev/urandom"); return 1; } if (argc != 4) return usage(argv[0]); uint32_t target_ip; if (!ip_parse(&target_ip, argv[1])) return usage(argv[0]); const unsigned portnum = strtoul(argv[2], NULL, 10); uint8_t server_pk[32]; unsigned server_pk_len = sizeof(server_pk); if (!base32_decode(server_pk, &server_pk_len, (const uint8_t *) argv[3], strlen(argv[3]), 1)) { perror("base32_decode"); return 1; } if (server_pk_len != 32) { fprintf(stderr, "Invalid server public key\n"); return 1; } static const uint8_t query[] = "\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03org\x00\x00\x02\x00\x01"; uint8_t pk[32]; crypto_box_curve25519xsalsa20poly1305_keypair(pk, global_secret_key); uint8_t nonce[24]; uint8_t nonce_and_box[4096]; randombytes(nonce, 12); memset(nonce + 12, 0, 12); memset(nonce_and_box, 0, 32); memcpy(nonce_and_box + 32, query, sizeof(query) - 1); crypto_box_curve25519xsalsa20poly1305 (nonce_and_box, nonce_and_box, 32 + sizeof(query) - 1, nonce, server_pk, global_secret_key); memcpy(nonce_and_box + 4, nonce, 12); write(1, pk, 32); write(1, nonce_and_box + 4, 12 + 16 + sizeof(query) - 1); uint8_t request[4096]; unsigned requestlen = sizeof(request) - 2; if (!dns_curve_request_build(request + 2, &requestlen, nonce_and_box + 4, 12 + 16 + sizeof(query) - 1, pk, (unsigned char *) "\x06google\x03org\x00")) { perror("dns_curve_request_build"); return 1; } requestlen += 2; const int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd < 0) { perror("socket"); return 1; } struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = target_ip; sin.sin_port = htons(portnum); ssize_t n; do { n = sendto(fd, request, requestlen, 0, (struct sockaddr *) &sin, sizeof(sin)); } while (n == -1 && errno == EINTR); if (n < 0) { perror("sendto"); return 1; } return 0; }
static uint8_t encryptHandshake(struct Message* message, struct Wrapper* wrapper) { assert(message->padding >= sizeof(union Headers_CryptoAuth) || !"not enough padding"); Message_shift(message, sizeof(union Headers_CryptoAuth)); union Headers_CryptoAuth* header = (union Headers_CryptoAuth*) message->bytes; // garbage the auth field to frustrate DPI and set the nonce (next 24 bytes after the auth) randombytes((uint8_t*) &header->handshake.auth, sizeof(union Headers_AuthChallenge) + 24); memcpy(&header->handshake.publicKey, wrapper->context->publicKey, 32); if (!knowHerKey(wrapper)) { return genReverseHandshake(message, wrapper, header); } // Password auth uint8_t* passwordHash = NULL; if (wrapper->password != NULL) { struct Auth auth; passwordHash = hashPassword(&auth, wrapper->password, wrapper->authType); memcpy(header->handshake.auth.bytes, &auth.challenge, sizeof(union Headers_AuthChallenge)); } header->handshake.auth.challenge.type = wrapper->authType; Headers_setPacketAuthRequired(&header->handshake.auth, wrapper->authenticatePackets); // set the session state uint32_t sessionState_be = Endian_hostToBigEndian32(wrapper->nextNonce); header->nonce = sessionState_be; if (wrapper->nextNonce == 0 || wrapper->nextNonce == 2) { // If we're sending a hello or a key crypto_box_curve25519xsalsa20poly1305_keypair(header->handshake.encryptedTempKey, wrapper->secret); if (wrapper->nextNonce == 0) { memcpy(wrapper->tempKey, header->handshake.encryptedTempKey, 32); } #ifdef Log_DEBUG assert(!Bits_isZero(header->handshake.encryptedTempKey, 32)); assert(!Bits_isZero(wrapper->secret, 32)); #endif } else if (wrapper->nextNonce == 3) { // Dupe key // If nextNonce is 1 then we have our pubkey stored in wrapper->tempKey, // If nextNonce is 3 we need to recalculate it each time // because tempKey the final secret. crypto_scalarmult_curve25519_base(header->handshake.encryptedTempKey, wrapper->secret); } else { // Dupe hello // wrapper->nextNonce == 1 // Our public key is cached in wrapper->tempKey so lets copy it out. memcpy(header->handshake.encryptedTempKey, wrapper->tempKey, 32); } uint8_t sharedSecret[32]; if (wrapper->nextNonce < 2) { if (wrapper->nextNonce == 0) { Log_debug(wrapper->context->logger, "Sending hello packet\n"); } else { Log_debug(wrapper->context->logger, "Sending repeat hello packet\n"); } getSharedSecret(sharedSecret, wrapper->context->privateKey, wrapper->herPerminentPubKey, passwordHash, wrapper->context->logger); wrapper->isInitiator = true; wrapper->nextNonce = 1; #ifdef Log_DEBUG assert(!Bits_isZero(header->handshake.encryptedTempKey, 32)); uint8_t myTempPubKey[32]; crypto_scalarmult_curve25519_base(myTempPubKey, wrapper->secret); assert(!memcmp(header->handshake.encryptedTempKey, myTempPubKey, 32)); #endif #ifdef Log_KEYS uint8_t tempKeyHex[65]; Hex_encode(tempKeyHex, 65, header->handshake.encryptedTempKey, 32); Log_keys1(wrapper->context->logger, "Wrapping temp public key:\n" " %s\n", tempKeyHex); #endif } else { if (wrapper->nextNonce == 2) { Log_debug(wrapper->context->logger, "Sending key packet\n"); } else { Log_debug(wrapper->context->logger, "Sending repeat key packet\n"); } // Handshake2 wrapper->tempKey holds her public temp key. // it was put there by receiveMessage() getSharedSecret(sharedSecret, wrapper->context->privateKey, wrapper->tempKey, passwordHash, wrapper->context->logger); wrapper->nextNonce = 3; #ifdef Log_KEYS uint8_t tempKeyHex[65]; Hex_encode(tempKeyHex, 65, wrapper->tempKey, 32); Log_keys1(wrapper->context->logger, "Using their temp public key:\n" " %s\n", tempKeyHex); #endif } // Shift message over the encryptedTempKey field. Message_shift(message, 32 - Headers_CryptoAuth_SIZE); encryptRndNonce(header->handshake.nonce, message, sharedSecret); Log_debug1(wrapper->context->logger, "Message length: %u\n", message->length); #ifdef Log_KEYS uint8_t sharedSecretHex[65]; printHexKey(sharedSecretHex, sharedSecret); uint8_t nonceHex[49]; Hex_encode(nonceHex, 49, header->handshake.nonce, 24); uint8_t cipherHex[65]; printHexKey(cipherHex, message->bytes); Log_keys3(wrapper->context->logger, "Encrypting message with:\n" " nonce: %s\n" " secret: %s\n" " cipher: %s\n", nonceHex, sharedSecretHex, cipherHex); #endif #ifdef Log_DEBUG assert(!Bits_isZero(header->handshake.encryptedTempKey, 32)); #endif // Shift it back -- encryptRndNonce adds 16 bytes of authenticator. Message_shift(message, Headers_CryptoAuth_SIZE - 32 - 16); return wrapper->wrappedInterface->sendMessage(message, wrapper->wrappedInterface); }
int crypto_box_keypair(unsigned char *pk, unsigned char *sk) { return crypto_box_curve25519xsalsa20poly1305_keypair(pk, sk); }
void dns_keys(unsigned char *pk, unsigned char *sk, unsigned char *nk) { randombytes(nk, 16); crypto_box_curve25519xsalsa20poly1305_keypair(pk, sk); }