/* an analogue to the random() function, but use prng_bytes */ long int get_random() { long int l; prng_bytes ((unsigned char *)&l, sizeof(l)); if (l < 0) l = -l; return l; }
/* create a temporary filename in directory */ const char * create_temp_file (const char *directory, const char *prefix, struct gc_arena *gc) { static unsigned int counter; struct buffer fname = alloc_buf_gc (256, gc); int fd; const char *retfname = NULL; unsigned int attempts = 0; do { uint8_t rndbytes[16]; const char *rndstr; ++attempts; ++counter; prng_bytes (rndbytes, sizeof rndbytes); rndstr = format_hex_ex (rndbytes, sizeof rndbytes, 40, 0, NULL, gc); buf_printf (&fname, PACKAGE "_%s_%s.tmp", prefix, rndstr); retfname = gen_path (directory, BSTR (&fname), gc); if (!retfname) { msg (M_FATAL, "Failed to create temporary filename and path"); return NULL; } /* Atomically create the file. Errors out if the file already exists. */ fd = platform_open (retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); if (fd != -1) { close (fd); return retfname; } else if (fd == -1 && errno != EEXIST) { /* Something else went wrong, no need to retry. */ struct gc_arena gcerr = gc_new (); msg (M_FATAL, "Could not create temporary file '%s': %s", retfname, strerror_ts (errno, &gcerr)); gc_free (&gcerr); return NULL; } } while (attempts < 6); msg (M_FATAL, "Failed to create temporary file after %i attempts", attempts); return NULL; }
/* * Prepend a random string to hostname to prevent DNS caching. * For example, foo.bar.gov would be modified to <random-chars>.foo.bar.gov. * Of course, this requires explicit support in the DNS server (wildcard). */ const char * hostname_randomize(const char *hostname, struct gc_arena *gc) { # define n_rnd_bytes 6 uint8_t rnd_bytes[n_rnd_bytes]; const char *rnd_str; struct buffer hname = alloc_buf_gc (strlen(hostname)+sizeof(rnd_bytes)*2+4, gc); prng_bytes (rnd_bytes, sizeof (rnd_bytes)); rnd_str = format_hex_ex (rnd_bytes, sizeof (rnd_bytes), 40, 0, NULL, gc); buf_printf(&hname, "%s.%s", rnd_str, hostname); return BSTR(&hname); # undef n_rnd_bytes }
void session_id_random (struct session_id *sid) { prng_bytes (sid->id, SID_SIZE); }
int ipsec_sa_init(struct ipsec_sa *ipsp) { int error = 0; char sa[SATOT_BUF]; size_t sa_len; #ifdef CONFIG_KLIPS_DEBUG char ipaddr_txt[ADDRTOA_BUF]; char ipaddr2_txt[ADDRTOA_BUF]; #endif #if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || \ defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) unsigned char kb[AHMD596_BLKLEN]; int i; #endif if (ipsp == NULL) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "ipsp is NULL, fatal\n"); SENDERR(EINVAL); } sa_len = KLIPS_SATOT(debug_pfkey, &ipsp->ips_said, 0, sa, sizeof(sa)); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "(pfkey defined) called for SA:%s\n", sa_len ? sa : " (error)"); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "calling init routine of %s%s%s\n", IPS_XFORM_NAME(ipsp)); switch (ipsp->ips_said.proto) { #ifdef CONFIG_KLIPS_IPIP case IPPROTO_IPIP: { ipsp->ips_xformfuncs = ipip_xform_funcs; #ifdef CONFIG_KLIPS_DEBUG sin_addrtot(ipsp->ips_addr_s, 0, ipaddr_txt, sizeof(ipaddr_txt)); sin_addrtot(ipsp->ips_addr_d, 0, ipaddr2_txt, sizeof(ipaddr2_txt)); KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "(pfkey defined) IPIP ipsec_sa set for %s->%s.\n", ipaddr_txt, ipaddr2_txt); #endif } break; #endif /* !CONFIG_KLIPS_IPIP */ #ifdef CONFIG_KLIPS_AH case IPPROTO_AH: ipsp->ips_xformfuncs = ah_xform_funcs; #ifdef CONFIG_KLIPS_OCF if (ipsec_ocf_sa_init(ipsp, ipsp->ips_authalg, 0)) break; #endif #ifdef CONFIG_KLIPS_ALG error = ipsec_alg_auth_key_create(ipsp); if ((error < 0) && (error != -EPROTO)) SENDERR(-error); if (error == -EPROTO) { /* perform manual key generation, ignore this particular error */ error = 0; #endif /* CONFIG_KLIPS_ALG */ switch (ipsp->ips_authalg) { # ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: { unsigned char *akp; unsigned int aks; MD5_CTX *ictx; MD5_CTX *octx; if (ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n" /*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a) + 0)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 1)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 2)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for md5_ctx.\n", (unsigned long) sizeof(struct md5_ctx)); if ((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) kb[i] = akp[i] ^ HMAC_IPAD; for (; i < AHMD596_BLKLEN; i++) kb[i] = HMAC_IPAD; ictx = &(((struct md5_ctx*)(ipsp->ips_key_a))->ictx); osMD5Init(ictx); osMD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); octx = &(((struct md5_ctx*)(ipsp->ips_key_a))->octx); osMD5Init(octx); osMD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ # ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: { unsigned char *akp; unsigned int aks; SHA1_CTX *ictx; SHA1_CTX *octx; if (ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect key size: %d bits -- must be %d bits\n" /*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a) + 0)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 1)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 2)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for sha1_ctx.\n", (unsigned long) sizeof(struct sha1_ctx)); if ((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) kb[i] = akp[i] ^ HMAC_IPAD; for (; i < AHMD596_BLKLEN; i++) kb[i] = HMAC_IPAD; ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); octx = &(((struct sha1_ctx*)(ipsp->ips_key_a))->octx); SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT(debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* zero key buffer -- paranoid */ memset(akp, 0, aks); kfree(akp); } break; # endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ default: KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "authalg=%d support not available in the kernel", ipsp->ips_authalg); SENDERR(EINVAL); } #ifdef CONFIG_KLIPS_ALG /* closure of the -EPROTO condition above */ } #endif break; #endif /* CONFIG_KLIPS_AH */ #ifdef CONFIG_KLIPS_ESP case IPPROTO_ESP: ipsp->ips_xformfuncs = esp_xform_funcs; { #ifdef CONFIG_KLIPS_OCF if (ipsec_ocf_sa_init(ipsp, ipsp->ips_authalg, ipsp->ips_encalg)) break; #endif #ifdef CONFIG_KLIPS_ALG error = ipsec_alg_enc_key_create(ipsp); if (error < 0) SENDERR(-error); error = ipsec_alg_auth_key_create(ipsp); if ((error < 0) && (error != -EPROTO)) SENDERR(-error); if (error == -EPROTO) { /* perform manual key generation, ignore this particular error */ error = 0; #endif /* CONFIG_KLIPS_ALG */ switch (ipsp->ips_authalg) { #if defined (CONFIG_KLIPS_AUTH_HMAC_MD5) || \ defined (CONFIG_KLIPS_AUTH_HMAC_SHA1) unsigned char *akp; unsigned int aks; #endif # ifdef CONFIG_KLIPS_AUTH_HMAC_MD5 case AH_MD5: { MD5_CTX *ictx; MD5_CTX *octx; if (ipsp->ips_key_bits_a != (AHMD596_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n" /*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHMD596_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac md5-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)(ipsp->ips_key_a)) + 0)), ntohl(*(((__u32 *)(ipsp->ips_key_a)) + 1)), ntohl(*(((__u32 *)(ipsp->ips_key_a)) + 2)), ntohl(*(((__u32 *)(ipsp->ips_key_a)) + 3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHMD596_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for md5_ctx.\n", (unsigned long) sizeof(struct md5_ctx)); if ((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct md5_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct md5_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) kb[i] = akp[i] ^ HMAC_IPAD; for (; i < AHMD596_BLKLEN; i++) kb[i] = HMAC_IPAD; ictx = &(((struct md5_ctx*)(ipsp->ips_key_a)) ->ictx); osMD5Init(ictx); osMD5Update(ictx, kb, AHMD596_BLKLEN); for (i = 0; i < AHMD596_BLKLEN; i++) kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); octx = &(((struct md5_ctx*)(ipsp->ips_key_a)) ->octx); osMD5Init(octx); osMD5Update(octx, kb, AHMD596_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "MD5 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ /* paranoid */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_KLIPS_AUTH_HMAC_MD5 */ # ifdef CONFIG_KLIPS_AUTH_HMAC_SHA1 case AH_SHA: { SHA1_CTX *ictx; SHA1_CTX *octx; if (ipsp->ips_key_bits_a != (AHSHA196_KLEN * 8)) { KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "incorrect authorisation key size: %d bits -- must be %d bits\n" /*octets (bytes)\n"*/, ipsp->ips_key_bits_a, AHSHA196_KLEN * 8); SENDERR(EINVAL); } # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "hmac sha1-96 key is 0x%08x %08x %08x %08x\n", ntohl(*(((__u32 *)ipsp->ips_key_a) + 0)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 1)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 2)), ntohl(*(((__u32 *)ipsp->ips_key_a) + 3))); # endif /* KLIPS_DIVULGE_HMAC_KEY */ ipsp->ips_auth_bits = AHSHA196_ALEN * 8; /* save the pointer to the key material */ akp = ipsp->ips_key_a; aks = ipsp->ips_key_a_size; KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "allocating %lu bytes for sha1_ctx.\n", (unsigned long) sizeof(struct sha1_ctx)); if ((ipsp->ips_key_a = (caddr_t) kmalloc(sizeof(struct sha1_ctx), GFP_ATOMIC)) == NULL) { ipsp->ips_key_a = akp; SENDERR(ENOMEM); } ipsp->ips_key_a_size = sizeof(struct sha1_ctx); for (i = 0; i < DIVUP(ipsp->ips_key_bits_a, 8); i++) kb[i] = akp[i] ^ HMAC_IPAD; for (; i < AHMD596_BLKLEN; i++) kb[i] = HMAC_IPAD; ictx = &(((struct sha1_ctx*)(ipsp->ips_key_a)) ->ictx); SHA1Init(ictx); SHA1Update(ictx, kb, AHSHA196_BLKLEN); for (i = 0; i < AHSHA196_BLKLEN; i++) kb[i] ^= (HMAC_IPAD ^ HMAC_OPAD); octx = &((struct sha1_ctx*)(ipsp->ips_key_a)) ->octx; SHA1Init(octx); SHA1Update(octx, kb, AHSHA196_BLKLEN); # if KLIPS_DIVULGE_HMAC_KEY KLIPS_PRINT( debug_pfkey && sysctl_ipsec_debug_verbose, "ipsec_sa_init: " "SHA1 ictx=0x%08x %08x %08x %08x octx=0x%08x %08x %08x %08x\n", ((__u32*)ictx)[0], ((__u32*)ictx)[1], ((__u32*)ictx)[2], ((__u32*)ictx)[3], ((__u32*)octx)[0], ((__u32*)octx)[1], ((__u32*)octx)[2], ((__u32*)octx)[3] ); # endif /* KLIPS_DIVULGE_HMAC_KEY */ memset(akp, 0, aks); kfree(akp); break; } # endif /* CONFIG_KLIPS_AUTH_HMAC_SHA1 */ case AH_NONE: break; default: KLIPS_PRINT(debug_pfkey, "ipsec_sa_init: " "authalg=%d support not available in the kernel.\n", ipsp->ips_authalg); SENDERR(EINVAL); } #ifdef CONFIG_KLIPS_ALG /* closure of the -EPROTO condition above */ } #endif ipsp->ips_iv_size = ipsp->ips_alg_enc->ixt_common.ixt_support. ias_ivlen / 8; /* Create IV */ if (ipsp->ips_iv_size) { if ((ipsp->ips_iv = (caddr_t) kmalloc(ipsp->ips_iv_size, GFP_ATOMIC)) == NULL) SENDERR(ENOMEM); prng_bytes(&ipsec_prng, (char *)ipsp->ips_iv, ipsp->ips_iv_size); ipsp->ips_iv_bits = ipsp->ips_iv_size * 8; } } break; #endif /* !CONFIG_KLIPS_ESP */ #ifdef CONFIG_KLIPS_IPCOMP case IPPROTO_COMP: ipsp->ips_xformfuncs = ipcomp_xform_funcs; ipsp->ips_comp_adapt_tries = 0; ipsp->ips_comp_adapt_skip = 0; ipsp->ips_comp_ratio_cbytes = 0; ipsp->ips_comp_ratio_dbytes = 0; #ifdef CONFIG_KLIPS_OCF if (ipsec_ocf_comp_sa_init(ipsp, ipsp->ips_encalg)) break; #endif ipsp->ips_comp_adapt_tries = 0; ipsp->ips_comp_adapt_skip = 0; ipsp->ips_comp_ratio_cbytes = 0; ipsp->ips_comp_ratio_dbytes = 0; break; #endif /* CONFIG_KLIPS_IPCOMP */ default: printk(KERN_ERR "KLIPS sa initialization: " "proto=%d unknown.\n", ipsp->ips_said.proto); SENDERR(EINVAL); } errlab: return error; }
void openvpn_encrypt (struct buffer *buf, struct buffer work, const struct crypto_options *opt, const struct frame* frame) { struct gc_arena gc; gc_init (&gc); if (buf->len > 0 && opt->key_ctx_bi) { struct key_ctx *ctx = &opt->key_ctx_bi->encrypt; /* Do Encrypt from buf -> work */ if (ctx->cipher) { uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH]; const int iv_size = cipher_ctx_iv_length (ctx->cipher); const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher); int outlen; if (cipher_kt_mode_cbc(cipher_kt)) { CLEAR (iv_buf); /* generate pseudo-random IV */ if (opt->flags & CO_USE_IV) prng_bytes (iv_buf, iv_size); /* Put packet ID in plaintext buffer or IV, depending on cipher mode */ if (opt->packet_id) { struct packet_id_net pin; packet_id_alloc_outgoing (&opt->packet_id->send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)); ASSERT (packet_id_write (&pin, buf, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM), true)); } } else if (cipher_kt_mode_ofb_cfb(cipher_kt)) { struct packet_id_net pin; struct buffer b; ASSERT (opt->flags & CO_USE_IV); /* IV and packet-ID required */ ASSERT (opt->packet_id); /* for this mode. */ packet_id_alloc_outgoing (&opt->packet_id->send, &pin, true); memset (iv_buf, 0, iv_size); buf_set_write (&b, iv_buf, iv_size); ASSERT (packet_id_write (&pin, &b, true, false)); } else /* We only support CBC, CFB, or OFB modes right now */ { ASSERT (0); } /* initialize work buffer with FRAME_HEADROOM bytes of prepend capacity */ ASSERT (buf_init (&work, FRAME_HEADROOM (frame))); /* set the IV pseudo-randomly */ if (opt->flags & CO_USE_IV) dmsg (D_PACKET_CONTENT, "ENCRYPT IV: %s", format_hex (iv_buf, iv_size, 0, &gc)); dmsg (D_PACKET_CONTENT, "ENCRYPT FROM: %s", format_hex (BPTR (buf), BLEN (buf), 80, &gc)); /* cipher_ctx was already initialized with key & keylen */ ASSERT (cipher_ctx_reset(ctx->cipher, iv_buf)); /* Buffer overflow check */ if (!buf_safe (&work, buf->len + cipher_ctx_block_size(ctx->cipher))) { msg (D_CRYPT_ERRORS, "ENCRYPT: buffer size error, bc=%d bo=%d bl=%d wc=%d wo=%d wl=%d cbs=%d", buf->capacity, buf->offset, buf->len, work.capacity, work.offset, work.len, cipher_ctx_block_size (ctx->cipher)); goto err; } /* Encrypt packet ID, payload */ ASSERT (cipher_ctx_update (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf))); ASSERT (buf_inc_len(&work, outlen)); /* Flush the encryption buffer */ ASSERT (cipher_ctx_final(ctx->cipher, BPTR (&work) + outlen, &outlen)); ASSERT (buf_inc_len(&work, outlen)); /* For all CBC mode ciphers, check the last block is complete */ ASSERT (cipher_kt_mode (cipher_kt) != OPENVPN_MODE_CBC || outlen == iv_size); /* prepend the IV to the ciphertext */ if (opt->flags & CO_USE_IV) { uint8_t *output = buf_prepend (&work, iv_size); ASSERT (output); memcpy (output, iv_buf, iv_size); } dmsg (D_PACKET_CONTENT, "ENCRYPT TO: %s", format_hex (BPTR (&work), BLEN (&work), 80, &gc)); } else /* No Encryption */ { if (opt->packet_id) { struct packet_id_net pin; packet_id_alloc_outgoing (&opt->packet_id->send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)); ASSERT (packet_id_write (&pin, buf, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM), true)); } work = *buf; } /* HMAC the ciphertext (or plaintext if !cipher) */ if (ctx->hmac) { uint8_t *output = NULL; hmac_ctx_reset (ctx->hmac); hmac_ctx_update (ctx->hmac, BPTR(&work), BLEN(&work)); output = buf_prepend (&work, hmac_ctx_size(ctx->hmac)); ASSERT (output); hmac_ctx_final (ctx->hmac, output); } *buf = work; } gc_free (&gc); return; err: crypto_clear_error(); buf->len = 0; gc_free (&gc); return; }