/* Construct MDP packet frame from overlay_mdp_frame structure (need to add return address from bindings list, and copy payload etc). This is for use by the SERVER. Clients should use overlay_mdp_send() */ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP, struct sockaddr_un *recvaddr,int recvaddrlen) { IN(); /* Prepare the overlay frame for dispatch */ struct overlay_frame *frame = calloc(1,sizeof(struct overlay_frame)); if (!frame) FATAL("Couldn't allocate frame buffer"); if (is_sid_any(mdp->out.src.sid)){ /* set source to ourselves */ frame->source = my_subscriber; bcopy(frame->source->sid, mdp->out.src.sid, SID_SIZE); }else if (is_broadcast(mdp->out.src.sid)){ /* This is rather naughty if it happens, since broadcasting a response can lead to all manner of nasty things. Picture a packet with broadcast as the source address, sent to, say, the MDP echo port on another node, and with a source port also of the echo port. Said echo will get multiplied many, many, many times over before the TTL finally reaches zero. So we just say no to any packet with a broadcast source address. (Of course we have other layers of protection against such shenanigens, such as using BPIs to smart-flood broadcasts, but security comes through depth.) */ op_free(frame); RETURN(WHY("Packet had broadcast address as source address")); }else{ // assume all local identities have already been unlocked and marked as SELF. frame->source = find_subscriber(mdp->out.src.sid, SID_SIZE, 0); if (!frame->source){ op_free(frame); RETURN(WHYF("Possible spoofing attempt, tried to send a packet from %s, which is an unknown SID", alloca_tohex_sid(mdp->out.src.sid))); } if (frame->source->reachable!=REACHABLE_SELF){ op_free(frame); RETURN(WHYF("Possible spoofing attempt, tried to send a packet from %s", alloca_tohex_sid(mdp->out.src.sid))); } } /* Work out if destination is broadcast or not */ if (overlay_mdp_check_binding(frame->source, mdp->out.src.port, userGeneratedFrameP, recvaddr, recvaddrlen)){ op_free(frame); RETURN(overlay_mdp_reply_error (mdp_named.poll.fd, (struct sockaddr_un *)recvaddr, recvaddrlen,8, "Source address is invalid (you must bind to a source address before" " you can send packets")); } if (is_broadcast(mdp->out.dst.sid)){ /* broadcast packets cannot be encrypted, so complain if MDP_NOCRYPT flag is not set. Also, MDP_NOSIGN must also be applied, until NaCl cryptobox keys can be used for signing. */ if (!(mdp->packetTypeAndFlags&MDP_NOCRYPT)){ op_free(frame); RETURN(overlay_mdp_reply_error(mdp_named.poll.fd, recvaddr,recvaddrlen,5, "Broadcast packets cannot be encrypted ")); } overlay_broadcast_generate_address(&frame->broadcast_id); frame->destination = NULL; }else{ frame->destination = find_subscriber(mdp->out.dst.sid, SID_SIZE, 1); } frame->ttl=64; /* normal TTL (XXX allow setting this would be a good idea) */ if (!frame->destination || frame->destination->reachable == REACHABLE_SELF) { /* Packet is addressed such that we should process it. */ overlay_saw_mdp_frame(mdp,gettime_ms()); if (frame->destination) { /* Is local, and is not broadcast, so shouldn't get sent out on the wire. */ op_free(frame); RETURN(0); } } /* give voice packets priority */ if (mdp->out.dst.port==MDP_PORT_VOMP) frame->type=OF_TYPE_DATA_VOICE; else frame->type=OF_TYPE_DATA; frame->prev=NULL; frame->next=NULL; frame->payload=ob_new(); int fe=0; /* Work out the disposition of the frame-> For now we are only worried about the crypto matters, and not compression that may be applied before encryption (since applying it after is useless as ciphered text should have maximum entropy). */ switch(mdp->packetTypeAndFlags&(MDP_NOCRYPT|MDP_NOSIGN)) { case 0: /* crypted and signed (using CryptoBox authcryption primitive) */ frame->modifiers=OF_CRYPTO_SIGNED|OF_CRYPTO_CIPHERED; /* Prepare payload */ ob_makespace(frame->payload, 1 // frame type (MDP) +1 // MDP version +4 // dst port +4 // src port +crypto_box_curve25519xsalsa20poly1305_NONCEBYTES +crypto_box_curve25519xsalsa20poly1305_ZEROBYTES +mdp->out.payload_length); { /* write cryptobox nonce */ unsigned char nonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES]; if (urandombytes(nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES)) { op_free(frame); RETURN(WHY("urandombytes() failed to generate nonce")); } fe|= ob_append_bytes(frame->payload,nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES); /* generate plain message with zero bytes and get ready to cipher it */ unsigned char plain[crypto_box_curve25519xsalsa20poly1305_ZEROBYTES +10+mdp->out.payload_length]; /* zero bytes */ int zb=crypto_box_curve25519xsalsa20poly1305_ZEROBYTES; bzero(&plain[0],zb); /* MDP version 1 */ plain[zb+0]=0x01; plain[zb+1]=0x01; /* Ports */ plain[zb+2]=(mdp->out.src.port>>24)&0xff; plain[zb+3]=(mdp->out.src.port>>16)&0xff; plain[zb+4]=(mdp->out.src.port>>8)&0xff; plain[zb+5]=(mdp->out.src.port>>0)&0xff; plain[zb+6]=(mdp->out.dst.port>>24)&0xff; plain[zb+7]=(mdp->out.dst.port>>16)&0xff; plain[zb+8]=(mdp->out.dst.port>>8)&0xff; plain[zb+9]=(mdp->out.dst.port>>0)&0xff; /* payload */ bcopy(&mdp->out.payload,&plain[zb+10],mdp->out.payload_length); int cipher_len=zb+10+mdp->out.payload_length; /* get pre-computed PKxSK bytes (the slow part of auth-cryption that can be retained and reused, and use that to do the encryption quickly. */ unsigned char *k=keyring_get_nm_bytes(&mdp->out.src,&mdp->out.dst); if (!k) { op_free(frame); RETURN(WHY("could not compute Curve25519(NxM)")); } /* Get pointer to place in frame where the ciphered text needs to go */ int cipher_offset=frame->payload->position; unsigned char *cipher_text=ob_append_space(frame->payload,cipher_len); if (fe||(!cipher_text)){ op_free(frame); RETURN(WHY("could not make space for ciphered text")); } /* Actually authcrypt the payload */ if (crypto_box_curve25519xsalsa20poly1305_afternm (cipher_text,plain,cipher_len,nonce,k)){ op_free(frame); RETURN(WHY("crypto_box_afternm() failed")); } /* now shuffle down 16 bytes to get rid of the temporary space that crypto_box uses. */ bcopy(&cipher_text[16],&cipher_text[0],cipher_len-16); frame->payload->position-=16; if (0) { DEBUG("authcrypted mdp frame"); dump("nm bytes",k,crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES); dump("nonce",nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES); dump("plain text",&plain[16],cipher_len-16); dump("cipher text",cipher_text,cipher_len-16); DEBUGF("frame->payload->length=%d,cipher_len-16=%d,cipher_offset=%d", frame->payload->position,cipher_len-16,cipher_offset); dump("frame",&frame->payload->bytes[0], frame->payload->position); } } break; case MDP_NOCRYPT: /* Payload is sent unencrypted, but signed. To save space we do a trick where we hash the payload, and get the signature of that, but do not send the hash itself, since that can be reproduced (and indeed must be for verification) at the receiver's end. As the signing key is implicit, and the hash is also implicit, we can chop out part of the signature and thus save some bytes. */ frame->modifiers=OF_CRYPTO_SIGNED; /* Prepare payload */ ob_makespace(frame->payload, 1 // frame type (MDP) +1 // MDP version +4 // dst port +4 // src port +crypto_sign_edwards25519sha512batch_BYTES +mdp->out.payload_length); { unsigned char *key=keyring_find_sas_private(keyring, frame->source->sid, NULL); if (!key) { op_free(frame); RETURN(WHY("could not find signing key")); } /* Build plain-text that includes header and hash it so that we can sign that hash. */ unsigned char hash[crypto_hash_sha512_BYTES]; int plain_len = 10+mdp->out.payload_length; unsigned char *plain = frame->payload->bytes + frame->payload->position; if (!plain) return WHY("Unable to allocate space for payload and signature"); /* MDP version 1 */ ob_append_byte(frame->payload,0x01); ob_append_byte(frame->payload,0x01); /* Destination port */ ob_append_ui32(frame->payload,mdp->out.src.port); ob_append_ui32(frame->payload,mdp->out.dst.port); ob_append_bytes(frame->payload,mdp->out.payload,mdp->out.payload_length); /* now hash it */ crypto_hash_sha512(hash,plain,plain_len); unsigned char signature[crypto_hash_sha512_BYTES +crypto_sign_edwards25519sha512batch_BYTES]; unsigned long long sig_len=0; crypto_sign_edwards25519sha512batch(signature,&sig_len, hash,crypto_hash_sha512_BYTES, key); if (!sig_len) { op_free(frame); RETURN(WHY("Signing MDP frame failed")); } if (0){ dump("payload", plain, plain_len); dump("signature", signature, sizeof(signature)); } /* chop hash out of middle of signature since it has to be recomputed at the far end, anyway, and ammend the two halves of the signature. */ ob_append_bytes(frame->payload,&signature[0],32); ob_append_bytes(frame->payload,&signature[32+crypto_hash_sha512_BYTES],32); } break; case MDP_NOSIGN|MDP_NOCRYPT: /* clear text and no signature */ frame->modifiers=0; /* Copy payload body in */ ob_makespace(frame->payload, 1 // frame type (MDP) +1 // MDP version +4 // dst port +4 // src port +mdp->out.payload_length); /* MDP version 1 */ ob_append_byte(frame->payload,0x01); ob_append_byte(frame->payload,0x01); /* Destination port */ ob_append_ui32(frame->payload,mdp->out.src.port); ob_append_ui32(frame->payload,mdp->out.dst.port); ob_append_bytes(frame->payload,mdp->out.payload,mdp->out.payload_length); break; case MDP_NOSIGN: default: /* ciphered, but not signed. This means we don't use CryptoBox, but rather a more compact means of representing the ciphered stream segment. */ op_free(frame); RETURN(WHY("Not implemented")); break; } // TODO include priority in packet header int qn=OQ_ORDINARY; /* Make sure voice traffic gets priority */ if ((frame->type&OF_TYPE_BITS)==OF_TYPE_DATA_VOICE) { qn=OQ_ISOCHRONOUS_VOICE; rhizome_saw_voice_traffic(); } frame->send_copies = mdp->out.send_copies; if (overlay_payload_enqueue(qn, frame)) op_free(frame); RETURN(0); }
/* Construct MDP packet frame from overlay_mdp_frame structure (need to add return address from bindings list, and copy payload etc). This is for use by the SERVER. Clients should use overlay_mdp_send() */ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP, struct sockaddr_un *recvaddr,int recvaddrlen) { IN(); /* Prepare the overlay frame for dispatch */ struct overlay_frame *frame = calloc(1,sizeof(struct overlay_frame)); if (!frame) FATAL("Couldn't allocate frame buffer"); if (is_sid_any(mdp->out.src.sid)){ /* set source to ourselves */ frame->source = my_subscriber; bcopy(frame->source->sid, mdp->out.src.sid, SID_SIZE); }else if (is_sid_broadcast(mdp->out.src.sid)){ /* This is rather naughty if it happens, since broadcasting a response can lead to all manner of nasty things. Picture a packet with broadcast as the source address, sent to, say, the MDP echo port on another node, and with a source port also of the echo port. Said echo will get multiplied many, many, many times over before the TTL finally reaches zero. So we just say no to any packet with a broadcast source address. (Of course we have other layers of protection against such shenanigens, such as using BPIs to smart-flood broadcasts, but security comes through depth.) */ op_free(frame); RETURN(WHY("Packet had broadcast address as source address")); }else{ // assume all local identities have already been unlocked and marked as SELF. frame->source = find_subscriber(mdp->out.src.sid, SID_SIZE, 0); if (!frame->source){ op_free(frame); RETURN(WHYF("Possible spoofing attempt, tried to send a packet from %s, which is an unknown SID", alloca_tohex_sid(mdp->out.src.sid))); } if (frame->source->reachable!=REACHABLE_SELF){ op_free(frame); RETURN(WHYF("Possible spoofing attempt, tried to send a packet from %s", alloca_tohex_sid(mdp->out.src.sid))); } } /* Work out if destination is broadcast or not */ if (overlay_mdp_check_binding(frame->source, mdp->out.src.port, userGeneratedFrameP, recvaddr, recvaddrlen)){ op_free(frame); RETURN(overlay_mdp_reply_error (mdp_named.poll.fd, (struct sockaddr_un *)recvaddr, recvaddrlen,8, "Source address is invalid (you must bind to a source address before" " you can send packets")); } if (is_sid_broadcast(mdp->out.dst.sid)){ /* broadcast packets cannot be encrypted, so complain if MDP_NOCRYPT flag is not set. Also, MDP_NOSIGN must also be applied, until NaCl cryptobox keys can be used for signing. */ if (!(mdp->packetTypeAndFlags&MDP_NOCRYPT)){ op_free(frame); RETURN(overlay_mdp_reply_error(mdp_named.poll.fd, recvaddr,recvaddrlen,5, "Broadcast packets cannot be encrypted ")); } overlay_broadcast_generate_address(&frame->broadcast_id); frame->destination = NULL; }else{ frame->destination = find_subscriber(mdp->out.dst.sid, SID_SIZE, 1); } frame->ttl = mdp->out.ttl; if (frame->ttl == 0) frame->ttl = PAYLOAD_TTL_DEFAULT; else if (frame->ttl > PAYLOAD_TTL_MAX) { op_free(frame); RETURN(overlay_mdp_reply_error(mdp_named.poll.fd, recvaddr,recvaddrlen,9, "TTL out of range")); } if (!frame->destination || frame->destination->reachable == REACHABLE_SELF) { /* Packet is addressed such that we should process it. */ overlay_saw_mdp_frame(NULL,mdp,gettime_ms()); if (frame->destination) { /* Is local, and is not broadcast, so shouldn't get sent out on the wire. */ op_free(frame); RETURN(0); } } frame->type=OF_TYPE_DATA; frame->prev=NULL; frame->next=NULL; struct overlay_buffer *plaintext=ob_new(); if (overlay_mdp_encode_ports(plaintext, mdp->out.dst.port, mdp->out.src.port)){ ob_free(plaintext); RETURN (-1); } if (ob_append_bytes(plaintext, mdp->out.payload, mdp->out.payload_length)){ ob_free(plaintext); RETURN(-1); } /* Work out the disposition of the frame-> For now we are only worried about the crypto matters, and not compression that may be applied before encryption (since applying it after is useless as ciphered text should have maximum entropy). */ switch(mdp->packetTypeAndFlags&(MDP_NOCRYPT|MDP_NOSIGN)) { case 0: /* crypted and signed (using CryptoBox authcryption primitive) */ frame->modifiers=OF_CRYPTO_SIGNED|OF_CRYPTO_CIPHERED; { int nm=crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES; int zb=crypto_box_curve25519xsalsa20poly1305_ZEROBYTES; int nb=crypto_box_curve25519xsalsa20poly1305_NONCEBYTES; int cz=crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES; /* generate plain message with zero bytes and get ready to cipher it */ int cipher_len=ob_position(plaintext); // TODO, add support for leading zero's in overlay_buffer's, then we don't need to copy the plain text again. unsigned char plain[zb+cipher_len]; /* zero bytes */ bzero(&plain[0],zb); bcopy(ob_ptr(plaintext),&plain[zb],cipher_len); cipher_len+=zb; ob_free(plaintext); frame->payload = ob_new(); unsigned char *nonce = ob_append_space(frame->payload, nb+cipher_len); unsigned char *cipher_text = nonce + nb; if (!nonce) RETURN(-1); if (generate_nonce(nonce,nb)) { op_free(frame); RETURN(WHY("generate_nonce() failed to generate nonce")); } // reserve the high bit of the nonce as a flag for transmitting a shorter nonce. nonce[0]&=0x7f; /* get pre-computed PKxSK bytes (the slow part of auth-cryption that can be retained and reused, and use that to do the encryption quickly. */ unsigned char *k=keyring_get_nm_bytes(mdp->out.src.sid, mdp->out.dst.sid); if (!k) { op_free(frame); RETURN(WHY("could not compute Curve25519(NxM)")); } /* Actually authcrypt the payload */ if (crypto_box_curve25519xsalsa20poly1305_afternm (cipher_text,plain,cipher_len,nonce,k)){ op_free(frame); RETURN(WHY("crypto_box_afternm() failed")); } if (0) { DEBUG("authcrypted mdp frame"); dump("nm",k,nm); dump("plain text",plain,sizeof(plain)); dump("nonce",nonce,nb); dump("cipher text",cipher_text,cipher_len); } /* now shuffle down to get rid of the temporary space that crypto_box uses. TODO extend overlay buffer so we don't need this. */ bcopy(&cipher_text[cz],&cipher_text[0],cipher_len-cz); frame->payload->position-=cz; if (0){ dump("frame",&frame->payload->bytes[0], frame->payload->position); } } break; case MDP_NOCRYPT: /* Payload is sent unencrypted, but signed. */ frame->modifiers=OF_CRYPTO_SIGNED; frame->payload = plaintext; ob_makespace(frame->payload,SIGNATURE_BYTES); if (crypto_sign_message(frame->source, frame->payload->bytes, frame->payload->allocSize, &frame->payload->position)){ op_free(frame); RETURN(-1); } break; case MDP_NOSIGN|MDP_NOCRYPT: /* clear text and no signature */ frame->modifiers=0; frame->payload = plaintext; break; case MDP_NOSIGN: default: /* ciphered, but not signed. This means we don't use CryptoBox, but rather a more compact means of representing the ciphered stream segment. */ op_free(frame); RETURN(WHY("Not implemented")); } frame->queue=mdp->out.queue; if (frame->queue==0) frame->queue = OQ_ORDINARY; if (overlay_payload_enqueue(frame)) op_free(frame); RETURN(0); OUT(); }
int overlay_mdp_decrypt(struct overlay_frame *f, overlay_mdp_frame *mdp) { IN(); int len=f->payload->sizeLimit - f->payload->position; unsigned char *b = NULL; unsigned char plain_block[len+16]; /* Indicate MDP message type */ mdp->packetTypeAndFlags=MDP_TX; switch(f->modifiers&OF_CRYPTO_BITS) { case 0: /* get payload */ b=&f->payload->bytes[f->payload->position]; mdp->packetTypeAndFlags|=MDP_NOCRYPT|MDP_NOSIGN; break; case OF_CRYPTO_CIPHERED: RETURN(WHY("decryption not implemented")); case OF_CRYPTO_SIGNED: { /* This call below will dispatch the request for the SAS if we don't already have it. In the meantime, we just drop the frame if the SAS is not available. */ if (!f->source->sas_valid){ keyring_send_sas_request(f->source); RETURN(WHY("SAS key not currently on record, cannot verify")); } /* get payload and following compacted signature */ b=&f->payload->bytes[f->payload->position]; len=f->payload->sizeLimit - f->payload->position - crypto_sign_edwards25519sha512batch_BYTES; /* reconstitute signature by putting hash between two halves of signature */ unsigned char signature[crypto_hash_sha512_BYTES +crypto_sign_edwards25519sha512batch_BYTES]; bcopy(&b[len],&signature[0],32); crypto_hash_sha512(&signature[32],b,len); if (0) dump("hash for verification",&signature[32],crypto_hash_sha512_BYTES); bcopy(&b[len+32],&signature[32+crypto_hash_sha512_BYTES],32); /* verify signature */ unsigned char m[crypto_hash_sha512_BYTES]; unsigned long long mlen=0; int result =crypto_sign_edwards25519sha512batch_open(m,&mlen, signature,sizeof(signature), f->source->sas_public); if (result) { WHY("Signature verification failed"); dump("data", b, len); dump("signature", signature, sizeof(signature)); RETURN(-1); } else if (0) DEBUG("signature check passed"); } mdp->packetTypeAndFlags|=MDP_NOCRYPT; break; case OF_CRYPTO_CIPHERED|OF_CRYPTO_SIGNED: { if (0) DEBUGF("crypted MDP frame for %s", alloca_tohex_sid(mdp->out.dst.sid)); unsigned char *k=keyring_get_nm_bytes(&mdp->out.dst,&mdp->out.src); unsigned char *nonce=&f->payload->bytes[f->payload->position]; int nb=crypto_box_curve25519xsalsa20poly1305_NONCEBYTES; int zb=crypto_box_curve25519xsalsa20poly1305_ZEROBYTES; if (!k) RETURN(WHY("I don't have the private key required to decrypt that")); bzero(&plain_block[0],crypto_box_curve25519xsalsa20poly1305_ZEROBYTES-16); int cipher_len=f->payload->sizeLimit - f->payload->position - nb; bcopy(&f->payload->bytes[nb + f->payload->position],&plain_block[16],cipher_len); if (0) { dump("nm bytes",k,crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES); dump("nonce",nonce,crypto_box_curve25519xsalsa20poly1305_NONCEBYTES); dump("cipher block",&plain_block[16],cipher_len); } if (crypto_box_curve25519xsalsa20poly1305_open_afternm (plain_block,plain_block,cipher_len+16,nonce,k)) { RETURN(WHYF("crypto_box_open_afternm() failed (forged or corrupted packet of %d bytes)",cipher_len+16)); } if (0) dump("plain block",&plain_block[zb],cipher_len-16); b=&plain_block[zb]; len=cipher_len-16; break; } } if (!b) RETURN(WHY("Failed to decode mdp payload")); int version=(b[0]<<8)+b[1]; if (version!=0x0101) RETURN(WHY("Saw unsupported MDP frame version")); /* extract MDP port numbers */ mdp->in.src.port=(b[2]<<24)+(b[3]<<16)+(b[4]<<8)+b[5]; mdp->in.dst.port=(b[6]<<24)+(b[7]<<16)+(b[8]<<8)+b[9]; if (0) DEBUGF("RX mdp dst.port=%d, src.port=%d", mdp->in.dst.port, mdp->in.src.port); mdp->in.payload_length=len-10; bcopy(&b[10],&mdp->in.payload[0],mdp->in.payload_length); RETURN(0); }
int overlay_mdp_decrypt(struct overlay_frame *f, overlay_mdp_frame *mdp) { IN(); /* Indicate MDP message type */ mdp->packetTypeAndFlags=MDP_TX; switch(f->modifiers&(OF_CRYPTO_CIPHERED|OF_CRYPTO_SIGNED)) { case 0: /* nothing to do, b already points to the plain text */ mdp->packetTypeAndFlags|=MDP_NOCRYPT|MDP_NOSIGN; RETURN(overlay_mdp_decode_header(f->payload, mdp)); case OF_CRYPTO_CIPHERED: RETURN(WHY("decryption not implemented")); case OF_CRYPTO_SIGNED: { int len = ob_remaining(f->payload); if (crypto_verify_message(f->source, ob_ptr(f->payload), &len)) RETURN(-1); mdp->packetTypeAndFlags|=MDP_NOCRYPT; ob_limitsize(f->payload, len + ob_position(f->payload)); RETURN(overlay_mdp_decode_header(f->payload, mdp)); } case OF_CRYPTO_CIPHERED|OF_CRYPTO_SIGNED: { if (0) DEBUGF("crypted MDP frame for %s", alloca_tohex_sid(f->destination->sid)); int nm=crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES; int nb=crypto_box_curve25519xsalsa20poly1305_NONCEBYTES; int zb=crypto_box_curve25519xsalsa20poly1305_ZEROBYTES; int cz=crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES; unsigned char *k=keyring_get_nm_bytes(f->destination->sid, f->source->sid); if (!k) RETURN(WHY("I don't have the private key required to decrypt that")); if (0){ dump("frame",&f->payload->bytes[f->payload->position], ob_remaining(f->payload)); } unsigned char *nonce=ob_get_bytes_ptr(f->payload, nb); if (!nonce) RETURN(WHYF("Expected %d bytes of nonce", nb)); int cipher_len=ob_remaining(f->payload); unsigned char *cipher_text=ob_get_bytes_ptr(f->payload, cipher_len); if (!cipher_text) RETURN(WHYF("Expected %d bytes of cipher text", cipher_len)); unsigned char plain_block[cipher_len+cz]; bzero(&plain_block[0],cz); bcopy(cipher_text,&plain_block[cz],cipher_len); if (0) { dump("nm bytes",k,nm); dump("nonce",nonce,nb); dump("cipher block",plain_block,sizeof(plain_block)); } cipher_len+=cz; if (crypto_box_curve25519xsalsa20poly1305_open_afternm (plain_block,plain_block,cipher_len,nonce,k)) { RETURN(WHYF("crypto_box_open_afternm() failed (from %s, to %s, len %d)", alloca_tohex_sid(f->source->sid), alloca_tohex_sid(f->destination->sid), cipher_len)); } if (0) dump("plain block",plain_block,sizeof(plain_block)); cipher_len -= zb; struct overlay_buffer *plaintext = ob_static(&plain_block[zb], cipher_len); ob_limitsize(plaintext,cipher_len); int ret=overlay_mdp_decode_header(plaintext, mdp); ob_free(plaintext); RETURN(ret); } } RETURN(WHY("Failed to decode mdp payload")); OUT(); }