int crypto_box_open_afternm(unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k) { return crypto_box_curve25519xsalsa20poly1305_open_afternm(m, c, clen, n, k); }
int crypto_box_curve25519xsalsa20poly1305_open( unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *pk, const unsigned char *sk) { unsigned char k[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES]; int ret; if (crypto_box_curve25519xsalsa20poly1305_beforenm(k, pk, sk) != 0) { return -1; } ret = crypto_box_curve25519xsalsa20poly1305_open_afternm(m, c, clen, n, k); sodium_memzero(k, sizeof k); return ret; }
/** * Decrypt and authenticate. * * @param nonce a 24 byte number, may be random, cannot repeat. * @param msg a message to encipher and authenticate. * @param secret a shared secret. * @return 0 if decryption is succeddful, otherwise -1. */ static inline int decryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32]) { if (msg->length < 16) { return -1; } assert(msg->padding >= 16); uint8_t* startAt = msg->bytes - 16; uint8_t paddingSpace[16]; memcpy(paddingSpace, startAt, 16); memset(startAt, 0, 16); if (crypto_box_curve25519xsalsa20poly1305_open_afternm( startAt, startAt, msg->length + 16, nonce, secret) != 0) { return -1; } memcpy(startAt, paddingSpace, 16); Message_shift(msg, -16); return 0; }
static int proto_decode(sigma_proto *instance, unsigned char* input, unsigned char* output, unsigned int len) { if ((len - crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES) > MAX_BUFFER_SIZE) { fprintf(stderr, "Decryption failed (packet length %i is above MAX_BUFFER_SIZE %i)\n", (len - crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES), MAX_BUFFER_SIZE); return 0; } if (len < crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES) { fprintf(stderr, "Short packet received: %d\n", len); return 0; } unsigned char tempbuffer[len + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES], tempbufferout[len + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES]; memset(tempbuffer, 0, crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES); memcpy(tempbuffer + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES, input, len); int result = crypto_box_curve25519xsalsa20poly1305_open_afternm( tempbufferout, tempbuffer, len + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES, n, ((sigma_proto_nacl*) instance)->precomp ); if (result) { fprintf(stderr, "Decryption failed (length %i, given result %i)\n", len, result); return 0; } memcpy(output, tempbufferout + crypto_box_curve25519xsalsa20poly1305_ZEROBYTES, len - crypto_box_curve25519xsalsa20poly1305_ZEROBYTES + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES); return len - crypto_box_curve25519xsalsa20poly1305_ZEROBYTES + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES; }
/** * Decrypt and authenticate. * * @param nonce a 24 byte number, may be random, cannot repeat. * @param msg a message to encipher and authenticate. * @param secret a shared secret. * @return 0 if decryption is succeddful, otherwise -1. */ static inline Gcc_USE_RET int decryptRndNonce(uint8_t nonce[24], struct Message* msg, uint8_t secret[32]) { if (msg->length < 16) { return -1; } Assert_true(msg->padding >= 16); uint8_t* startAt = msg->bytes - 16; uint8_t paddingSpace[16]; Bits_memcpyConst(paddingSpace, startAt, 16); Bits_memset(startAt, 0, 16); if (!Defined(NSA_APPROVED)) { if (crypto_box_curve25519xsalsa20poly1305_open_afternm( startAt, startAt, msg->length + 16, nonce, secret) != 0) { return -1; } } Bits_memcpyConst(startAt, paddingSpace, 16); Message_shift(msg, -16, NULL); return 0; }
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(); }