// Decode auth message S3 static int authDecodeS3(struct s_auth_state *authstate, const unsigned char *msg, const int msg_len) { int msgnum; int decmsg_len; unsigned char decmsg[auth_MAXMSGSIZE_S3]; if(msg_len > 6) { memcpy(decmsg, msg, 6); msgnum = utilReadInt16(&decmsg[4]); if(msgnum == (authstate->state + 1)) { decmsg_len = (4 + 2 + cryptoDec(&authstate->crypto_ctx[auth_CRYPTOCTX_CNEG], &decmsg[(4 + 2)], (auth_MAXMSGSIZE_S3 - 2 - 4), &msg[(4 + 2)], (msg_len - 2 - 4), auth_CNEGHMACSIZE, auth_CNEGIVSIZE)); if(decmsg_len >= (4 + 2 + auth_NONCESIZE + seq_SIZE + 4 + 8)) { memcpy(authstate->remote_keygen_nonce, &decmsg[(4 + 2)], auth_NONCESIZE); if((msgnum % 2) == 0) { memcpy(&authstate->keygen_nonce[0], authstate->local_keygen_nonce, auth_NONCESIZE); memcpy(&authstate->keygen_nonce[auth_NONCESIZE], authstate->remote_keygen_nonce, auth_NONCESIZE); } else { memcpy(&authstate->keygen_nonce[0], authstate->remote_keygen_nonce, auth_NONCESIZE); memcpy(&authstate->keygen_nonce[auth_NONCESIZE], authstate->local_keygen_nonce, auth_NONCESIZE); } memcpy(authstate->remote_seq, &decmsg[(4 + 2 + auth_NONCESIZE)], seq_SIZE); authstate->remote_peerid = utilReadInt32(&decmsg[(4 + 2 + auth_NONCESIZE + seq_SIZE)]); memcpy(authstate->remote_flags, &decmsg[(4 + 2 + auth_NONCESIZE + seq_SIZE + 4)], 8); return 1; } } } return 0; }
// decode packet static int packetDecode(struct s_packet_data *data, const unsigned char *pbuf, const int pbuf_size, struct s_crypto *ctx, struct s_seq_state *seqstate) { unsigned char dec_buf[pbuf_size]; int len; // decrypt packet if(pbuf_size < (packet_PEERID_SIZE + packet_HMAC_SIZE + packet_IV_SIZE)) { return 0; } len = cryptoDec(ctx, dec_buf, pbuf_size, &pbuf[packet_PEERID_SIZE], (pbuf_size - packet_PEERID_SIZE), packet_HMAC_SIZE, packet_IV_SIZE); if(len < packet_CRHDR_SIZE) { return 0; }; // get packet data data->peerid = packetGetPeerID(pbuf); data->seq = utilReadInt64(&dec_buf[packet_CRHDR_SEQ_START]); if(seqstate != NULL) if(!seqVerify(seqstate, data->seq)) { return 0; } data->pl_options = dec_buf[packet_CRHDR_PLOPT_START]; data->pl_type = dec_buf[packet_CRHDR_PLTYPE_START]; data->pl_length = utilReadInt16(&dec_buf[packet_CRHDR_PLLEN_START]); if(!(data->pl_length > 0)) { data->pl_length = 0; return 0; } if(len < (packet_CRHDR_SIZE + data->pl_length)) { return 0; } if(data->pl_length > data->pl_buf_size) { return 0; } memcpy(data->pl_buf, &dec_buf[packet_CRHDR_SIZE], data->pl_length); // return length of decoded payload return (data->pl_length); }
// Decode auth message S2 static int authDecodeS2(struct s_auth_state *authstate, const unsigned char *msg, const int msg_len) { int msgnum; int nksize; int signsize; int decmsg_len; unsigned char hmac[auth_HMACSIZE]; unsigned char siginbuf[auth_SIGINBUFSIZE]; unsigned char decmsg[auth_MAXMSGSIZE_S2]; int siginbuf_size; if(msg_len > 10) { memcpy(decmsg, msg, 6); msgnum = utilReadInt16(&decmsg[4]); if(msgnum == (authstate->state + 1)) { decmsg_len = (4 + 2 + cryptoDec(&authstate->crypto_ctx[auth_CRYPTOCTX_IDP], &decmsg[(4 + 2)], (auth_MAXMSGSIZE_S2 - 2 - 4), &msg[(4 + 2)], (msg_len - 2 - 4), auth_IDPHMACSIZE, auth_IDPIVSIZE)); // decrypt IDP layer if(decmsg_len > 10) { nksize = utilReadInt16(&decmsg[(4 + 2)]); if((nksize > nodekey_MINSIZE) && (decmsg_len > (10 + nksize))) { signsize = utilReadInt16(&decmsg[(4 + 4 + nksize)]); if((signsize > 0) && (decmsg_len >= (10 + nksize + signsize + auth_HMACSIZE))) { // check message length if(cryptoHMAC(&authstate->crypto_ctx[auth_CRYPTOCTX_AUTH], hmac, auth_HMACSIZE, &decmsg[(4 + 4)], nksize)) { // generate HMAC tag if(memcmp(&decmsg[(10 + nksize + signsize)], hmac, auth_HMACSIZE) == 0) { // verify HMAC tag if(nodekeyLoadDER(&authstate->remote_nodekey, &decmsg[(4 + 4)], nksize)) { // load remote public key if(memcmp(authstate->remote_nodekey.nodeid.id, authstate->local_nodekey->nodeid.id, nodeid_SIZE) != 0) { // check if remote public key is different from local public key siginbuf_size = authGenRemoteSigIn(authstate, siginbuf, &decmsg[4]); if(rsaVerify(&authstate->remote_nodekey.key, &decmsg[(10 + nksize)], signsize, siginbuf, siginbuf_size)) { // verify signature return 1; } } } } } } } } } } return 0; }
// Decode auth message S1 static int authDecodeS1(struct s_auth_state *authstate, const unsigned char *msg, const int msg_len) { int msgnum; int dhsize; unsigned char shared_nonce[auth_NONCESIZE + auth_NONCESIZE]; unsigned char checksum[8]; if(msg_len > (4 + 2 + 8 + 4 + auth_NONCESIZE + 2)) { msgnum = utilReadInt16(&msg[4]); if(msgnum == (authstate->state + 1)) { if(memcmp(authstate->local_sesstoken, &msg[(4 + 2 + 8)], 4) == 0) { dhsize = utilReadInt16(&msg[(4 + 2 + 8 + 4 + auth_NONCESIZE)]); if((dhsize > dh_MINSIZE) && (msg_len >= (4 + 2 + 8 + 4 + auth_NONCESIZE + 2 + dhsize))) { if(cryptoCalculateSHA256(checksum, 8, &msg[(4 + 2 + 8)], (4 + auth_NONCESIZE + 2 + dhsize))) { if(memcmp(checksum, &msg[(4 + 2)], 8) == 0) { authstate->remote_dhkey_size = dhsize; memcpy(authstate->remote_dhkey, &msg[(4 + 2 + 8 + 4 + auth_NONCESIZE + 2)], dhsize); memcpy(authstate->remote_nonce, &msg[(4 + 2 + 8 + 4)], auth_NONCESIZE); if(memcmp(authstate->local_nonce, authstate->remote_nonce, auth_NONCESIZE) != 0) { if((msgnum % 2) == 0) { memcpy(&shared_nonce[0], &msg[(4 + 2 + 8 + 4)], auth_NONCESIZE); memcpy(&shared_nonce[auth_NONCESIZE], authstate->local_nonce, auth_NONCESIZE); } else { memcpy(&shared_nonce[0], authstate->local_nonce, auth_NONCESIZE); memcpy(&shared_nonce[auth_NONCESIZE], &msg[(4 + 2 + 8 + 4)], auth_NONCESIZE); } if(dhGenCryptoKeys(authstate->crypto_ctx, auth_CRYPTOCTX_COUNT, authstate->dhstate, &msg[(4 + 2 + 8 + 4 + auth_NONCESIZE + 2)], dhsize, shared_nonce, (auth_NONCESIZE + auth_NONCESIZE))) { return 1; } } } } } } } } return 0; }
// Decode auth message S4 static int authDecodeS4(struct s_auth_state *authstate, const unsigned char *msg, const int msg_len) { int msgnum; unsigned char hmac[auth_HMACSIZE]; if(msg_len >= (6 + auth_NONCESIZE + auth_CNEGHMACSIZE)) { msgnum = utilReadInt16(&msg[4]); if(msgnum == (authstate->state + 1)) { if(cryptoHMAC(&authstate->crypto_ctx[auth_CRYPTOCTX_CNEG], hmac, auth_HMACSIZE, &msg[6], auth_NONCESIZE)) { if(memcmp(hmac, &msg[(6 + auth_NONCESIZE)], auth_CNEGHMACSIZE) == 0) { return 1; } } } } return 0; }
// Decode auth message S0 static int authDecodeS0(struct s_auth_state *authstate, const unsigned char *msg, const int msg_len) { int msgnum; unsigned char checksum[8]; if(msg_len >= (4 + 2 + 8 + 4 + 4 + netid_SIZE)) { msgnum = utilReadInt16(&msg[4]); if(msgnum == (authstate->state + 1)) { if(cryptoCalculateSHA256(checksum, 8, &msg[(4 + 2 + 8)], (4 + 4 + netid_SIZE))) { if(memcmp(checksum, &msg[(4 + 2)], 8) == 0) { if(memcmp(authstate->netid->id, &msg[(4 + 2 + 8 + 4 + 4)], netid_SIZE) == 0) { memcpy(authstate->remote_authid, &msg[(4 + 2 + 8)], 4); memcpy(authstate->remote_sesstoken, &msg[(4 + 2 + 8 + 4)], 4); return 1; } } } } } return 0; }