/* * Make safe mutations to key to ensure it is valid, * such as ensuring correct parity on DES keys. * * This routine cannot guarantee it will generate a good * key. You must always call check_key after this routine * to make sure. */ void fixup_key (struct key *key, const struct key_type *kt) { struct gc_arena gc = gc_new (); if (kt->cipher) { #ifdef ENABLE_DEBUG const struct key orig = *key; #endif const int ndc = key_des_num_cblocks (kt->cipher); if (ndc) key_des_fixup (key->cipher, kt->cipher_length, ndc); #ifdef ENABLE_DEBUG if (check_debug_level (D_CRYPTO_DEBUG)) { if (memcmp (orig.cipher, key->cipher, kt->cipher_length)) dmsg (D_CRYPTO_DEBUG, "CRYPTO INFO: fixup_key: before=%s after=%s", format_hex (orig.cipher, kt->cipher_length, 0, &gc), format_hex (key->cipher, kt->cipher_length, 0, &gc)); } #endif } gc_free (&gc); }
/* * Generate a random key. If key_type is provided, make * sure generated key is valid for key_type. */ void generate_key_random (struct key *key, const struct key_type *kt) { int cipher_len = MAX_CIPHER_KEY_LENGTH; int hmac_len = MAX_HMAC_KEY_LENGTH; struct gc_arena gc = gc_new (); do { CLEAR (*key); if (kt) { if (kt->cipher && kt->cipher_length > 0 && kt->cipher_length <= cipher_len) cipher_len = kt->cipher_length; if (kt->digest && kt->hmac_length > 0 && kt->hmac_length <= hmac_len) hmac_len = kt->hmac_length; } if (!rand_bytes (key->cipher, cipher_len) || !rand_bytes (key->hmac, hmac_len)) msg (M_FATAL, "ERROR: Random number generator cannot obtain entropy for key generation"); dmsg (D_SHOW_KEY_SOURCE, "Cipher source entropy: %s", format_hex (key->cipher, cipher_len, 0, &gc)); dmsg (D_SHOW_KEY_SOURCE, "HMAC source entropy: %s", format_hex (key->hmac, hmac_len, 0, &gc)); if (kt) fixup_key (key, kt); } while (kt && !check_key (key, kt)); gc_free (&gc); }
// show_vote // called when the SYSFS file is accessed. // // SYSFS attributes, // "/sys/class/usb/vote0/device/voting" is read // // tvote vs. vote_dev vs usb_vote - chose vote_dev --kgb // static ssize_t show_vote( struct device *dev, struct device_attribute *attr, char * buf ) { int bytes = 0; // bytes written to buf by sprintf // not including final '\0' struct usb_interface *intf = to_usb_interface(dev); struct usb_vote * vote_dev = usb_get_intfdata(intf); char page[100]; // sysfs output char vstring[10]; // vote as a string // Print the vote -- if its printable and not whitespace. if (vote_dev->votecast >= '!' && vote_dev->votecast <= '~') { bytes = sprintf(page, "Current vote: %c. ", vote_dev->votecast); } printk(KERN_DEBUG "%s with bytes=%d, page=\"%s\"\n", __FUNCTION__, bytes, page); // Print out the hex value of the vote sprintf(vstring, "%c", vote_dev->votecast); format_hex(&page[bytes], 1, vstring); bytes = sprintf(buf, "%s\n", page); printk(KERN_DEBUG "%s with bytes=%d, buf=\"%s\"\n", __FUNCTION__, bytes, buf); return bytes; } // show_vote()
/* given a key and key_type, build a key_ctx */ void init_key_ctx (struct key_ctx *ctx, struct key *key, const struct key_type *kt, int enc, const char *prefix) { struct gc_arena gc = gc_new (); CLEAR (*ctx); if (kt->cipher && kt->cipher_length > 0) { ALLOC_OBJ(ctx->cipher, cipher_ctx_t); cipher_ctx_init (ctx->cipher, key->cipher, kt->cipher_length, kt->cipher, enc); msg (D_HANDSHAKE, "%s: Cipher '%s' initialized with %d bit key", prefix, cipher_kt_name(kt->cipher), kt->cipher_length *8); dmsg (D_SHOW_KEYS, "%s: CIPHER KEY: %s", prefix, format_hex (key->cipher, kt->cipher_length, 0, &gc)); dmsg (D_CRYPTO_DEBUG, "%s: CIPHER block_size=%d iv_size=%d", prefix, cipher_kt_block_size(kt->cipher), cipher_kt_iv_size(kt->cipher)); } if (kt->digest && kt->hmac_length > 0) { ALLOC_OBJ(ctx->hmac, hmac_ctx_t); hmac_ctx_init (ctx->hmac, key->hmac, kt->hmac_length, kt->digest); msg (D_HANDSHAKE, "%s: Using %d bit message hash '%s' for HMAC authentication", prefix, md_kt_size(kt->digest) * 8, md_kt_name(kt->digest)); dmsg (D_SHOW_KEYS, "%s: HMAC KEY: %s", prefix, format_hex (key->hmac, kt->hmac_length, 0, &gc)); dmsg (D_CRYPTO_DEBUG, "%s: HMAC size=%d block_size=%d", prefix, md_kt_size(kt->digest), hmac_ctx_size(ctx->hmac)); } gc_free (&gc); }
static bool tls_crypt_v2_wrap_client_key(struct buffer *wkc, const struct key2 *src_key, const struct buffer *src_metadata, struct key_ctx *server_key, struct gc_arena *gc) { cipher_ctx_t *cipher_ctx = server_key->cipher; struct buffer work = alloc_buf_gc(TLS_CRYPT_V2_MAX_WKC_LEN + cipher_ctx_block_size(cipher_ctx), gc); /* Calculate auth tag and synthetic IV */ uint8_t *tag = buf_write_alloc(&work, TLS_CRYPT_TAG_SIZE); if (!tag) { msg(M_WARN, "ERROR: could not write tag"); return false; } uint16_t net_len = htons(sizeof(src_key->keys) + BLEN(src_metadata) + TLS_CRYPT_V2_TAG_SIZE + sizeof(uint16_t)); hmac_ctx_t *hmac_ctx = server_key->hmac; hmac_ctx_reset(hmac_ctx); hmac_ctx_update(hmac_ctx, (void *)&net_len, sizeof(net_len)); hmac_ctx_update(hmac_ctx, (void *)src_key->keys, sizeof(src_key->keys)); hmac_ctx_update(hmac_ctx, BPTR(src_metadata), BLEN(src_metadata)); hmac_ctx_final(hmac_ctx, tag); dmsg(D_CRYPTO_DEBUG, "TLS-CRYPT WRAP TAG: %s", format_hex(tag, TLS_CRYPT_TAG_SIZE, 0, gc)); /* Use the 128 most significant bits of the tag as IV */ ASSERT(cipher_ctx_reset(cipher_ctx, tag)); /* Overflow check (OpenSSL requires an extra block in the dst buffer) */ if (buf_forward_capacity(&work) < (sizeof(src_key->keys) + BLEN(src_metadata) + sizeof(net_len) + cipher_ctx_block_size(cipher_ctx))) { msg(M_WARN, "ERROR: could not crypt: insufficient space in dst"); return false; } /* Encrypt */ int outlen = 0; ASSERT(cipher_ctx_update(cipher_ctx, BEND(&work), &outlen, (void *)src_key->keys, sizeof(src_key->keys))); ASSERT(buf_inc_len(&work, outlen)); ASSERT(cipher_ctx_update(cipher_ctx, BEND(&work), &outlen, BPTR(src_metadata), BLEN(src_metadata))); ASSERT(buf_inc_len(&work, outlen)); ASSERT(cipher_ctx_final(cipher_ctx, BEND(&work), &outlen)); ASSERT(buf_inc_len(&work, outlen)); ASSERT(buf_write(&work, &net_len, sizeof(net_len))); return buf_copy(wkc, &work); }
const char * md5sum (uint8_t *buf, int len, int n_print_chars, struct gc_arena *gc) { uint8_t digest[MD5_DIGEST_LENGTH]; const md_kt_t *md5_kt = md_kt_get("MD5"); md_full(md5_kt, buf, len, digest); return format_hex (digest, MD5_DIGEST_LENGTH, n_print_chars, gc); }
format_hexdump::format_hexdump(const void * p_buffer,t_size p_bytes,const char * p_spacing) { t_size n; const t_uint8 * buffer = (const t_uint8*)p_buffer; for(n=0;n<p_bytes;n++) { if (n > 0 && p_spacing != 0) m_formatter << p_spacing; m_formatter << format_hex(buffer[n],2); } }
static void bio_debug_data (const char *mode, BIO *bio, const uint8_t *buf, int len, const char *desc) { struct gc_arena gc = gc_new (); if (len > 0) { open_biofp(); fprintf(biofp, "BIO_%s %s time=" time_format " bio=" ptr_format " len=%d data=%s\n", mode, desc, time (NULL), (ptr_type)bio, len, format_hex (buf, len, 0, &gc)); fflush (biofp); } gc_free (&gc); }
int nrx_wxevent_connection_lost(struct net_device *dev, we_conn_lost_ind_t *data) { char bssid[13]; format_hex(bssid, sizeof(bssid), data->bssid.octet, sizeof(data->bssid.octet)); send_nrx_event(dev, "CONNLOST,type=%#x,bssid=%s,reason=%#x", data->type, bssid, data->reason_code); return 0; }
/* * Print key material */ void key2_print (const struct key2* k, const struct key_type *kt, const char* prefix0, const char* prefix1) { struct gc_arena gc = gc_new (); ASSERT (k->n == 2); dmsg (D_SHOW_KEY_SOURCE, "%s (cipher): %s", prefix0, format_hex (k->keys[0].cipher, kt->cipher_length, 0, &gc)); dmsg (D_SHOW_KEY_SOURCE, "%s (hmac): %s", prefix0, format_hex (k->keys[0].hmac, kt->hmac_length, 0, &gc)); dmsg (D_SHOW_KEY_SOURCE, "%s (cipher): %s", prefix1, format_hex (k->keys[1].cipher, kt->cipher_length, 0, &gc)); dmsg (D_SHOW_KEY_SOURCE, "%s (hmac): %s", prefix1, format_hex (k->keys[1].hmac, kt->hmac_length, 0, &gc)); gc_free (&gc); }
static int to_str(void *item,char *dst) { mbag_item_t *i= item; char *d = dst; int utf8 = format_is_utf8(bstr16_data(i->data), bstr16_len(i->data)); if (utf8) { d += sprintf(d, "%.*s", bstr16_len(i->data), bstr16_data(i->data)); } else { d += sprintf(d, ".x"); d += format_hex(d, bstr16_data(i->data), bstr16_len(i->data)); } return d-dst; }
static void send_custom_event(struct net_device *dev, const char *prefix, const char *suffix, void *buf, size_t len) { union iwreq_data wrqu; char custom[IW_CUSTOM_MAX]; size_t cend = 0; snprintf(custom, sizeof(custom), "%s", prefix); cend = strlen(custom); cend += format_hex(custom + cend, sizeof(custom) - cend, buf, len); cend += snprintf(custom + cend, sizeof(custom) - cend, "%s", suffix); wrqu.data.length = strlen(custom); wrqu.data.flags = 0; wrqu.data.pointer = (caddr_t)0xdeadbeef; wireless_send_event(dev, IWEVCUSTOM, &wrqu, custom); }
_format_hw_dn(char *buf, size_t size, const_efidp dp) { efi_guid_t edd10_guid = EDD10_HARDWARE_VENDOR_PATH_GUID; off_t off = 0; switch (dp->subtype) { case EFIDP_HW_PCI: off += format(buf, size, off, "Pci(0x%"PRIx32",0x%"PRIx32")", dp->pci.device, dp->pci.function); break; case EFIDP_HW_PCCARD: off += format(buf, size, off, "PcCard(0x%"PRIx32")", dp->pccard.function); break; case EFIDP_HW_MMIO: off += format(buf, size, off, "MemoryMapped(%"PRIu32",0x%"PRIx64",0x%"PRIx64")", dp->mmio.memory_type, dp->mmio.starting_address, dp->mmio.ending_address); break; case EFIDP_HW_VENDOR: if (!efi_guid_cmp(&dp->hw_vendor.vendor_guid, &edd10_guid)) { off += format_helper(format_edd10_guid, buf, size, off, dp); } else { off += format_vendor(buf, size, off, "VenHw", dp); } break; case EFIDP_HW_CONTROLLER: off += format(buf, size, off, "Ctrl(0x%"PRIx32")", dp->controller.controller); break; case EFIDP_HW_BMC: off += format(buf, size, off, "BMC(%d,0x%"PRIx64")", dp->bmc.interface_type, dp->bmc.base_addr); break; default: off += format(buf, size, off, "HardwarePath(%d,", dp->subtype); off += format_hex(buf, size, off, (uint8_t *)dp+4, efidp_node_size(dp)-4); off += format(buf,size,off,")"); break; } return off; }
void ObjDumper::SectionHexDump(StringRef SecName, const uint8_t *Section, size_t Size) { const uint8_t *SecContent = Section; const uint8_t *SecEnd = Section + Size; W.startLine() << "Hex dump of section '" << SecName << "':\n"; for (const uint8_t *SecPtr = SecContent; SecPtr < SecEnd; SecPtr += 16) { const uint8_t *TmpSecPtr = SecPtr; uint8_t i; uint8_t k; W.startLine() << format_hex(SecPtr - SecContent, 10); W.startLine() << ' '; for (i = 0; TmpSecPtr < SecEnd && i < 4; ++i) { for (k = 0; TmpSecPtr < SecEnd && k < 4; k++, TmpSecPtr++) { uint8_t Val = *(reinterpret_cast<const uint8_t *>(TmpSecPtr)); W.startLine() << format_hex_no_prefix(Val, 2); } W.startLine() << ' '; } // We need to print the correct amount of spaces to match the format. // We are adding the (4 - i) last rows that are 8 characters each. // Then, the (4 - i) spaces that are in between the rows. // Least, if we cut in a middle of a row, we add the remaining characters, // which is (8 - (k * 2)) if (i < 4) W.startLine() << format("%*c", (4 - i) * 8 + (4 - i) + (8 - (k * 2)), ' '); TmpSecPtr = SecPtr; for (i = 0; TmpSecPtr + i < SecEnd && i < 16; ++i) { if (isprint(TmpSecPtr[i])) W.startLine() << TmpSecPtr[i]; else W.startLine() << '.'; } W.startLine() << '\n'; } }
int nrx_wxevent_michael_mic_failure(struct net_device *dev, void *bssid, int group_failure) { unsigned int keyid = 0; #if WIRELESS_EXT < 18 char buf[128]; char addr[32]; format_hex(addr, sizeof(addr), bssid, 6); snprintf(buf, sizeof(buf), "MLME-MICHAELMICFAILURE.indication(keyid=%u %s addr=%s)", keyid, group_failure ? "broadcast" : "unicast", addr); send_custom_event(dev, buf, "", NULL, 0); #else struct iw_michaelmicfailure mic; union iwreq_data wrqu; wrqu.data.length = sizeof(mic); wrqu.data.flags = 0; mic.flags = keyid; if(group_failure) mic.flags |= IW_MICFAILURE_GROUP; else mic.flags |= IW_MICFAILURE_PAIRWISE; mic.src_addr.sa_family = ARPHRD_ETHER; memcpy(mic.src_addr.sa_data, bssid, 6); memset(mic.tsc, 0, sizeof(mic.tsc)); wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char*)&mic); #endif return 0; }
static int write_header(struct archive_write *a, struct archive_entry *entry) { int64_t ino; struct cpio *cpio; const char *p, *path; int pathlength, ret, ret_final; char h[c_header_size]; struct archive_string_conv *sconv; struct archive_entry *entry_main; size_t len; int pad; cpio = (struct cpio *)a->format_data; ret_final = ARCHIVE_OK; sconv = get_sconv(a); #if defined(_WIN32) && !defined(__CYGWIN__) /* Make sure the path separators in pahtname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate ustar data"); return(ARCHIVE_FATAL); } if (entry != entry_main) entry = entry_main; else entry_main = NULL; #else entry_main = NULL; #endif ret = archive_entry_pathname_l(entry, &path, &len, sconv); if (ret != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); ret_final = ARCHIVE_FATAL; goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate pathname '%s' to %s", archive_entry_pathname(entry), archive_string_conversion_charset_name(sconv)); ret_final = ARCHIVE_WARN; } pathlength = (int)len + 1; /* Include trailing null. */ memset(h, 0, c_header_size); format_hex(0x070701, h + c_magic_offset, c_magic_size); format_hex(archive_entry_devmajor(entry), h + c_devmajor_offset, c_devmajor_size); format_hex(archive_entry_devminor(entry), h + c_devminor_offset, c_devminor_size); ino = archive_entry_ino64(entry); if (ino > 0xffffffff) { archive_set_error(&a->archive, ERANGE, "large inode number truncated"); ret_final = ARCHIVE_WARN; } /* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */ format_hex(ino & 0xffffffff, h + c_ino_offset, c_ino_size); format_hex(archive_entry_mode(entry), h + c_mode_offset, c_mode_size); format_hex(archive_entry_uid(entry), h + c_uid_offset, c_uid_size); format_hex(archive_entry_gid(entry), h + c_gid_offset, c_gid_size); format_hex(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size); if (archive_entry_filetype(entry) == AE_IFBLK || archive_entry_filetype(entry) == AE_IFCHR) { format_hex(archive_entry_rdevmajor(entry), h + c_rdevmajor_offset, c_rdevmajor_size); format_hex(archive_entry_rdevminor(entry), h + c_rdevminor_offset, c_rdevminor_size); } else { format_hex(0, h + c_rdevmajor_offset, c_rdevmajor_size); format_hex(0, h + c_rdevminor_offset, c_rdevminor_size); } format_hex(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); format_hex(pathlength, h + c_namesize_offset, c_namesize_size); format_hex(0, h + c_checksum_offset, c_checksum_size); /* Non-regular files don't store bodies. */ if (archive_entry_filetype(entry) != AE_IFREG) archive_entry_set_size(entry, 0); /* Symlinks get the link written as the body of the entry. */ ret = archive_entry_symlink_l(entry, &p, &len, sconv); if (ret != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Likname"); ret_final = ARCHIVE_FATAL; goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate linkname '%s' to %s", archive_entry_symlink(entry), archive_string_conversion_charset_name(sconv)); ret_final = ARCHIVE_WARN; } if (len > 0 && p != NULL && *p != '\0') ret = format_hex(strlen(p), h + c_filesize_offset, c_filesize_size); else ret = format_hex(archive_entry_size(entry), h + c_filesize_offset, c_filesize_size); if (ret) { archive_set_error(&a->archive, ERANGE, "File is too large for this format."); ret_final = ARCHIVE_FAILED; goto exit_write_header; } ret = __archive_write_output(a, h, c_header_size); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } /* Pad pathname to even length. */ ret = __archive_write_output(a, path, pathlength); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } pad = PAD4(pathlength + c_header_size); if (pad) { ret = __archive_write_output(a, "\0\0\0", pad); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } } cpio->entry_bytes_remaining = archive_entry_size(entry); cpio->padding = (int)PAD4(cpio->entry_bytes_remaining); /* Write the symlink now. */ if (p != NULL && *p != '\0') { ret = __archive_write_output(a, p, strlen(p)); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } pad = PAD4(strlen(p)); ret = __archive_write_output(a, "\0\0\0", pad); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } } exit_write_header: if (entry_main) archive_entry_free(entry_main); return (ret_final); }
_format_message_dn(char *buf, size_t size, const_efidp dp) { ssize_t off = 0; ssize_t sz; switch (dp->subtype) { case EFIDP_MSG_ATAPI: off += format(buf, size, off, "Ata(%d,%d,%d)", dp->atapi.primary, dp->atapi.slave, dp->atapi.lun); break; case EFIDP_MSG_SCSI: off += format(buf, size, off, "SCSI(%d,%d)", dp->scsi.target, dp->scsi.lun); break; case EFIDP_MSG_FIBRECHANNEL: off += format(buf, size, off, "Fibre(%"PRIx64",%"PRIx64")", le64_to_cpu(dp->fc.wwn), le64_to_cpu(dp->fc.lun)); break; case EFIDP_MSG_FIBRECHANNELEX: off += format(buf, size, off, "Fibre(%"PRIx64",%"PRIx64")", be64_to_cpu(dp->fc.wwn), be64_to_cpu(dp->fc.lun)); break; case EFIDP_MSG_1394: off += format(buf, size, off, "I1394(0x%"PRIx64")", dp->firewire.guid); break; case EFIDP_MSG_USB: off += format(buf, size, off, "USB(%d,%d)", dp->usb.parent_port, dp->usb.interface); break; case EFIDP_MSG_I2O: off += format(buf, size, off, "I2O(%d)", dp->i2o.target); break; case EFIDP_MSG_INFINIBAND: if (dp->infiniband.resource_flags & EFIDP_INFINIBAND_RESOURCE_IOC_SERVICE) { off += format(buf, size, off, "Infiniband(%08x,%"PRIx64"%"PRIx64",%"PRIx64",%"PRIu64",%"PRIu64")", dp->infiniband.resource_flags, dp->infiniband.port_gid[1], dp->infiniband.port_gid[0], dp->infiniband.service_id, dp->infiniband.target_port_id, dp->infiniband.device_id); } else { off += format(buf, size, off, "Infiniband(%08x,%"PRIx64"%"PRIx64",", dp->infiniband.resource_flags, dp->infiniband.port_gid[1], dp->infiniband.port_gid[0]); off += format_guid(buf, size, off, (efi_guid_t *) &dp->infiniband.ioc_guid); off += format(buf, size, off, ",%"PRIu64",%"PRIu64")", dp->infiniband.target_port_id, dp->infiniband.device_id); } break; case EFIDP_MSG_MAC_ADDR: off += format(buf, size, off, "MAC("); off += format_hex(buf, size, off, dp->mac_addr.mac_addr, dp->mac_addr.if_type < 2 ? 6 : sizeof(dp->mac_addr.mac_addr)); off += format(buf, size, off, ",%d)", dp->mac_addr.if_type); break; case EFIDP_MSG_IPv4: { efidp_ipv4_addr const *a = &dp->ipv4_addr; off += format(buf, size, off, "IPv4(%hhu.%hhu.%hhu.%hhu:%hu<->%hhu.%hhu.%hhu.%hhu:%hu,%hx,%hhx)", a->local_ipv4_addr[0], a->local_ipv4_addr[1], a->local_ipv4_addr[2], a->local_ipv4_addr[3], a->local_port, a->remote_ipv4_addr[0], a->remote_ipv4_addr[1], a->remote_ipv4_addr[2], a->remote_ipv4_addr[3], a->remote_port, a->protocol, a->static_ip_addr); break; } case EFIDP_MSG_VENDOR: { struct { efi_guid_t guid; char label[40]; ssize_t (*formatter)(char *buf, size_t size, const_efidp dp); } subtypes[] = { { EFIDP_PC_ANSI_GUID, "VenPcAnsi" }, { EFIDP_VT_100_GUID, "VenVt100" }, { EFIDP_VT_100_PLUS_GUID, "VenVt100Plus" }, { EFIDP_VT_UTF8_GUID, "VenUtf8" }, { EFIDP_MSG_DEBUGPORT_GUID, "DebugPort" }, { EFIDP_MSG_UART_GUID, "", format_uart }, { EFIDP_MSG_SAS_GUID, "", format_sas }, { efi_guid_empty, "" } }; char *label = NULL; ssize_t (*formatter)(char *buf, size_t size, const_efidp dp) = NULL; for (int i = 0; !efi_guid_is_zero(&subtypes[i].guid); i++) { if (efi_guid_cmp(&subtypes[i].guid, &dp->msg_vendor.vendor_guid)) continue; label = subtypes[i].label; formatter = subtypes[i].formatter; break; } if (!label && !formatter) { off += format_vendor(buf, size, off, "VenMsg", dp); break; } else if (formatter) { off += format_helper(formatter, buf, size, off, dp); break; } off += format(buf, size, off, "%s(", label); if (efidp_node_size(dp) > (ssize_t)(sizeof (efidp_header) + sizeof (efi_guid_t))) { off += format_hex(buf, size, off, dp->msg_vendor.vendor_data, efidp_node_size(dp) - sizeof (efidp_header) - sizeof (efi_guid_t)); } break; } case EFIDP_MSG_IPv6: { efidp_ipv6_addr const *a = &dp->ipv6_addr; char *addr0 = NULL; char *addr1 = NULL; sz = format_ipv6_port(addr0, 0, 0, a->local_ipv6_addr, a->local_port); if (sz < 0) return sz; addr0 = alloca(sz+1); sz = format_ipv6_port(addr0, sz, 0, a->local_ipv6_addr, a->local_port); if (sz < 0) return sz; sz = format_ipv6_port(addr1, 0, 0, a->remote_ipv6_addr, a->remote_port); if (sz < 0) return sz; addr1 = alloca(sz+1); sz = format_ipv6_port(addr1, sz, 0, a->remote_ipv6_addr, a->remote_port); if (sz < 0) return sz; off += format(buf, size, off, "IPv6(%s<->%s,%hx,%hhx)", addr0, addr1, a->protocol, a->ip_addr_origin); break; } case EFIDP_MSG_UART: { int parity = dp->uart.parity; char parity_label[] = "DNEOMS"; int stop_bits = dp->uart.stop_bits; char *sb_label[] = {"D", "1", "1.5", "2"}; off += format(buf, size, off, "Uart(%"PRIu64",%d,", dp->uart.baud_rate ? dp->uart.baud_rate : 115200, dp->uart.data_bits ? dp->uart.data_bits : 8); off += format(buf, size, off, parity > 5 ? "%d," : "%c,", parity > 5 ? parity : parity_label[parity]); if (stop_bits > 3) off += format(buf, size, off, "%d)", stop_bits); else off += format(buf, size, off, "%s)", sb_label[stop_bits]); break; } case EFIDP_MSG_USB_CLASS: off += format_helper(format_usb_class, buf, size, off, dp); break; case EFIDP_MSG_USB_WWID: off += format(buf, size, off, "UsbWwid(%"PRIx16",%"PRIx16",%d,", dp->usb_wwid.vendor_id, dp->usb_wwid.product_id, dp->usb_wwid.interface); off += format_ucs2(buf, size, off, dp->usb_wwid.serial_number, (efidp_node_size(dp) - offsetof(efidp_usb_wwid, serial_number)) / 2 + 1); off += format(buf, size, off, ")"); break; case EFIDP_MSG_LUN: off += format(buf, size, off, "Unit(%d)", dp->lun.lun); break; case EFIDP_MSG_SATA: off += format(buf, size, off, "Sata(%d,%d,%d)", dp->sata.hba_port, dp->sata.port_multiplier_port, dp->sata.lun); break; case EFIDP_MSG_ISCSI: { size_t sz = efidp_node_size(dp) - offsetof(efidp_iscsi, target_name); if (sz > EFIDP_ISCSI_MAX_TARGET_NAME_LEN) sz = EFIDP_ISCSI_MAX_TARGET_NAME_LEN; char target_name[sz + 1]; memcpy(target_name, dp->iscsi.target_name, sz); target_name[sz] = '\0'; uint64_t lun; memcpy(&lun, dp->iscsi.lun, sizeof (lun)); off += format(buf, size, off, "iSCSI(%s,%d,0x%"PRIx64",%s,%s,%s,%s)", target_name, dp->iscsi.tpgt, be64_to_cpu(lun), (dp->iscsi.options >> EFIDP_ISCSI_HEADER_DIGEST_SHIFT) & EFIDP_ISCSI_HEADER_CRC32 ? "CRC32" : "None", (dp->iscsi.options >> EFIDP_ISCSI_DATA_DIGEST_SHIFT) & EFIDP_ISCSI_DATA_CRC32 ? "CRC32" : "None", (dp->iscsi.options >> EFIDP_ISCSI_AUTH_SHIFT) & EFIDP_ISCSI_AUTH_NONE ? "None" : \ (dp->iscsi.options >> EFIDP_ISCSI_CHAP_SHIFT) & EFIDP_ISCSI_CHAP_UNI ? "CHAP_UNI" : "CHAP_BI", dp->iscsi.protocol == 0 ? "TCP" : "Unknown"); break; } case EFIDP_MSG_VLAN: off += format(buf, size, off, "Vlan(%d)", dp->vlan.vlan_id); break; case EFIDP_MSG_SAS_EX: off += format_sas(buf, size, dp); break; case EFIDP_MSG_NVME: off += format(buf, size, off, "NVMe(0x%"PRIx32"," "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X)", dp->nvme.namespace_id, dp->nvme.ieee_eui_64[0], dp->nvme.ieee_eui_64[1], dp->nvme.ieee_eui_64[2], dp->nvme.ieee_eui_64[3], dp->nvme.ieee_eui_64[4], dp->nvme.ieee_eui_64[5], dp->nvme.ieee_eui_64[6], dp->nvme.ieee_eui_64[7]); break; case EFIDP_MSG_URI: { size_t sz = efidp_node_size(dp) - offsetof(efidp_uri, uri); char uri[sz + 1]; memcpy(uri, dp->uri.uri, sz); uri[sz] = '\0'; off += format(buf, size, off, "Uri(%s)", uri); break; } case EFIDP_MSG_UFS: off += format(buf, size, off, "UFS(%d,0x%02x)", dp->ufs.target_id, dp->ufs.lun); break; case EFIDP_MSG_SD: off += format(buf, size, off, "SD(%d)", dp->sd.slot_number); break; default: off += format(buf, size, off, "Msg(%d,", dp->subtype); off += format_hex(buf, size, off, (uint8_t *)dp+4, efidp_node_size(dp)-4); off += format(buf,size,off,")"); break; } return off; }
static void unroll_tree(pTHX_ struct sljit_compiler* compiler, HV* seenops, OP* op, OP* end) { // XXX: This basically is the algorithm from walk_exec in B::Concise, but I // think it could be done better. (Maybe core will get something like // codegen?). while (op && op != end) { const char* op_hex = format_hex(op); // Have we visited this op already? if (hv_exists(seenops, op_hex, strlen(op_hex))) { DEBUGf((" ;; Already seen %s [0x%s]\n", OP_NAME(op), op_hex)); // Insert jump to it emit_jump(compiler, op); // We know we have followed all the next pointers for this chain, // so: break; } // Seen op hv_store(seenops, op_hex, 0, &PL_sv_yes, strlen(op_hex)); if (op->op_type == OP_CUSTOM) { // All bets are off sljit_emit_return(compiler, SLJIT_MEM, (sljit_w) &PL_op); } else if (OP_CLASS(op) == OA_LOGOP) { unroll_branching_op(compiler, seenops, op, op->op_next, cLOGOPx(op)->op_other); } else if (op->op_type == OP_SUBST && cPMOPx(op)->op_pmstashstartu.op_pmreplstart) { unroll_branching_op(compiler, seenops, op, op->op_next, cPMOPx(op)->op_pmstashstartu.op_pmreplstart); } else if (op->op_type == OP_GREPSTART || op->op_type == OP_MAPSTART) { unroll_branching_op(compiler, seenops, op, op->op_next->op_next, cLOGOPx(op->op_next)->op_other); } else if (op->op_type == OP_NEXT || op->op_type == OP_LAST || op->op_type == OP_REDO) { sljit_emit_return(compiler, SLJIT_MEM, (sljit_w) &PL_op); //need_patch = 1; XXX } else if (op->op_type == OP_FLIP || op->op_type == OP_GOTO) { sljit_emit_return(compiler, SLJIT_MEM, (sljit_w) &PL_op); //need_patch = 1; XXX } else if (op->op_type == OP_ENTERSUB) { sljit_emit_return(compiler, SLJIT_MEM, (sljit_w) &PL_op); //need_patch = 1; XXX } else if (op->op_type == OP_RETURN || op->op_type == OP_LEAVESUB || op->op_type == OP_REQUIRE) { // XXX: leavesublv? unroll_op(compiler, op); sljit_emit_return(compiler, SLJIT_MEM, (sljit_w) &PL_op); } else { unroll_op(compiler, op); #ifdef DEBUG // Ensure returned OP is actually the one we expect struct sljit_jump *jump1 = sljit_emit_cmp(compiler, SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, (sljit_w) op->op_next); sljit_emit_op0(compiler, SLJIT_BREAKPOINT); sljit_set_label(jump1, sljit_emit_label(compiler)); #endif } op = op->op_next; } }
static bool tls_crypt_v2_unwrap_client_key(struct key2 *client_key, struct buffer *metadata, struct buffer wrapped_client_key, struct key_ctx *server_key) { const char *error_prefix = __func__; bool ret = false; struct gc_arena gc = gc_new(); /* The crypto API requires one extra cipher block of buffer head room when * decrypting, which nicely matches the tag size of WKc. So * TLS_CRYPT_V2_MAX_WKC_LEN is always large enough for the plaintext. */ uint8_t plaintext_buf_data[TLS_CRYPT_V2_MAX_WKC_LEN] = { 0 }; struct buffer plaintext = { 0 }; dmsg(D_TLS_DEBUG_MED, "%s: unwrapping client key (len=%d): %s", __func__, BLEN(&wrapped_client_key), format_hex(BPTR(&wrapped_client_key), BLEN(&wrapped_client_key), 0, &gc)); if (TLS_CRYPT_V2_MAX_WKC_LEN < BLEN(&wrapped_client_key)) { CRYPT_ERROR("wrapped client key too big"); } /* Decrypt client key and metadata */ uint16_t net_len = 0; const uint8_t *tag = BPTR(&wrapped_client_key); if (BLEN(&wrapped_client_key) < sizeof(net_len)) { CRYPT_ERROR("failed to read length"); } memcpy(&net_len, BEND(&wrapped_client_key) - sizeof(net_len), sizeof(net_len)); if (ntohs(net_len) != BLEN(&wrapped_client_key)) { dmsg(D_TLS_DEBUG_LOW, "%s: net_len=%u, BLEN=%i", __func__, ntohs(net_len), BLEN(&wrapped_client_key)); CRYPT_ERROR("invalid length"); } buf_inc_len(&wrapped_client_key, -(int)sizeof(net_len)); if (!buf_advance(&wrapped_client_key, TLS_CRYPT_TAG_SIZE)) { CRYPT_ERROR("failed to read tag"); } if (!cipher_ctx_reset(server_key->cipher, tag)) { CRYPT_ERROR("failed to initialize IV"); } buf_set_write(&plaintext, plaintext_buf_data, sizeof(plaintext_buf_data)); int outlen = 0; if (!cipher_ctx_update(server_key->cipher, BPTR(&plaintext), &outlen, BPTR(&wrapped_client_key), BLEN(&wrapped_client_key))) { CRYPT_ERROR("could not decrypt client key"); } ASSERT(buf_inc_len(&plaintext, outlen)); if (!cipher_ctx_final(server_key->cipher, BEND(&plaintext), &outlen)) { CRYPT_ERROR("cipher final failed"); } ASSERT(buf_inc_len(&plaintext, outlen)); /* Check authentication */ uint8_t tag_check[TLS_CRYPT_TAG_SIZE] = { 0 }; hmac_ctx_reset(server_key->hmac); hmac_ctx_update(server_key->hmac, (void *)&net_len, sizeof(net_len)); hmac_ctx_update(server_key->hmac, BPTR(&plaintext), BLEN(&plaintext)); hmac_ctx_final(server_key->hmac, tag_check); if (memcmp_constant_time(tag, tag_check, sizeof(tag_check))) { dmsg(D_CRYPTO_DEBUG, "tag : %s", format_hex(tag, sizeof(tag_check), 0, &gc)); dmsg(D_CRYPTO_DEBUG, "tag_check: %s", format_hex(tag_check, sizeof(tag_check), 0, &gc)); CRYPT_ERROR("client key authentication error"); } if (buf_len(&plaintext) < sizeof(client_key->keys)) { CRYPT_ERROR("failed to read client key"); } memcpy(&client_key->keys, BPTR(&plaintext), sizeof(client_key->keys)); ASSERT(buf_advance(&plaintext, sizeof(client_key->keys))); if (!buf_copy(metadata, &plaintext)) { CRYPT_ERROR("metadata too large for supplied buffer"); } ret = true; error_exit: if (!ret) { secure_memzero(client_key, sizeof(*client_key)); } buf_clear(&plaintext); gc_free(&gc); return ret; }
bool establish_http_proxy_passthru (struct http_proxy_info *p, socket_descriptor_t sd, /* already open to proxy */ const char *host, /* openvpn server remote */ const int port, /* openvpn server port */ struct buffer *lookahead, volatile int *signal_received) { struct gc_arena gc = gc_new (); char buf[512]; char buf2[128]; char get[80]; int status; int nparms; bool ret = false; bool processed = false; /* get user/pass if not previously given */ if (p->auth_method == HTTP_AUTH_BASIC || p->auth_method == HTTP_AUTH_DIGEST || p->auth_method == HTTP_AUTH_NTLM) get_user_pass_http (p, false); /* are we being called again after getting the digest server nonce in the previous transaction? */ if (p->auth_method == HTTP_AUTH_DIGEST && p->proxy_authenticate) { nparms = 1; status = 407; } else { /* format HTTP CONNECT message */ openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s", host, port, p->options.http_version); msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); /* send HTTP CONNECT message to proxy */ if (!send_line_crlf (sd, buf)) goto error; openvpn_snprintf(buf, sizeof(buf), "Host: %s", host); if (!send_line_crlf(sd, buf)) goto error; /* send User-Agent string if provided */ if (p->options.user_agent) { openvpn_snprintf (buf, sizeof(buf), "User-Agent: %s", p->options.user_agent); if (!send_line_crlf (sd, buf)) goto error; } /* auth specified? */ switch (p->auth_method) { case HTTP_AUTH_NONE: break; case HTTP_AUTH_BASIC: openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Basic %s", username_password_as_base64 (p, &gc)); msg (D_PROXY, "Attempting Basic Proxy-Authorization"); dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf); if (!send_line_crlf (sd, buf)) goto error; break; #if NTLM case HTTP_AUTH_NTLM: case HTTP_AUTH_NTLM2: /* keep-alive connection */ openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive"); if (!send_line_crlf (sd, buf)) goto error; openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s", ntlm_phase_1 (p, &gc)); msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 1"); dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf); if (!send_line_crlf (sd, buf)) goto error; break; #endif default: ASSERT (0); } /* send empty CR, LF */ if (!send_crlf (sd)) goto error; /* receive reply from proxy */ if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) goto error; /* remove trailing CR, LF */ chomp (buf); msg (D_PROXY, "HTTP proxy returned: '%s'", buf); /* parse return string */ nparms = sscanf (buf, "%*s %d", &status); } /* check for a "407 Proxy Authentication Required" response */ while (nparms >= 1 && status == 407) { msg (D_PROXY, "Proxy requires authentication"); if (p->auth_method == HTTP_AUTH_BASIC && !processed) { processed = true; } else if ((p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) && !processed) /* check for NTLM */ { #if NTLM /* look for the phase 2 response */ while (true) { if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) goto error; chomp (buf); msg (D_PROXY, "HTTP proxy returned: '%s'", buf); openvpn_snprintf (get, sizeof get, "%%*s NTLM %%%ds", (int) sizeof (buf2) - 1); nparms = sscanf (buf, get, buf2); buf2[127] = 0; /* we only need the beginning - ensure it's null terminated. */ /* check for "Proxy-Authenticate: NTLM TlRM..." */ if (nparms == 1) { /* parse buf2 */ msg (D_PROXY, "auth string: '%s'", buf2); break; } } /* if we are here then auth string was got */ msg (D_PROXY, "Received NTLM Proxy-Authorization phase 2 response"); /* receive and discard everything else */ while (recv_line (sd, NULL, 0, 2, true, NULL, signal_received)) ; /* now send the phase 3 reply */ /* format HTTP CONNECT message */ openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s", host, port, p->options.http_version); msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); /* send HTTP CONNECT message to proxy */ if (!send_line_crlf (sd, buf)) goto error; /* keep-alive connection */ openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive"); if (!send_line_crlf (sd, buf)) goto error; /* send HOST etc, */ openvpn_snprintf (buf, sizeof(buf), "Host: %s", host); msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); if (!send_line_crlf (sd, buf)) goto error; msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 3"); { const char *np3 = ntlm_phase_3 (p, buf2, &gc); if (!np3) { msg (D_PROXY, "NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server"); goto error; } openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s", np3); } msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); if (!send_line_crlf (sd, buf)) goto error; /* ok so far... */ /* send empty CR, LF */ if (!send_crlf (sd)) goto error; /* receive reply from proxy */ if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) goto error; /* remove trailing CR, LF */ chomp (buf); msg (D_PROXY, "HTTP proxy returned: '%s'", buf); /* parse return string */ nparms = sscanf (buf, "%*s %d", &status); processed = true; #endif } #if PROXY_DIGEST_AUTH else if (p->auth_method == HTTP_AUTH_DIGEST && !processed) { char *pa = p->proxy_authenticate; const int method = p->auth_method; ASSERT(pa); if (method == HTTP_AUTH_DIGEST) { const char *http_method = "CONNECT"; const char *nonce_count = "00000001"; const char *qop = "auth"; const char *username = p->up.username; const char *password = p->up.password; char *opaque_kv = ""; char uri[128]; uint8_t cnonce_raw[8]; uint8_t *cnonce; HASHHEX session_key; HASHHEX response; const char *realm = get_pa_var("realm", pa, &gc); const char *nonce = get_pa_var("nonce", pa, &gc); const char *algor = get_pa_var("algorithm", pa, &gc); const char *opaque = get_pa_var("opaque", pa, &gc); /* generate a client nonce */ ASSERT(rand_bytes(cnonce_raw, sizeof(cnonce_raw))); cnonce = make_base64_string2(cnonce_raw, sizeof(cnonce_raw), &gc); /* build the digest response */ openvpn_snprintf (uri, sizeof(uri), "%s:%d", host, port); if (opaque) { const int len = strlen(opaque)+16; opaque_kv = gc_malloc(len, false, &gc); openvpn_snprintf (opaque_kv, len, ", opaque=\"%s\"", opaque); } DigestCalcHA1(algor, username, realm, password, nonce, (char *)cnonce, session_key); DigestCalcResponse(session_key, nonce, nonce_count, (char *)cnonce, qop, http_method, uri, NULL, response); /* format HTTP CONNECT message */ openvpn_snprintf (buf, sizeof(buf), "%s %s HTTP/%s", http_method, uri, p->options.http_version); msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); /* send HTTP CONNECT message to proxy */ if (!send_line_crlf (sd, buf)) goto error; /* send HOST etc, */ openvpn_snprintf (buf, sizeof(buf), "Host: %s", host); msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); if (!send_line_crlf (sd, buf)) goto error; /* send digest response */ openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=%s, nc=%s, cnonce=\"%s\", response=\"%s\"%s", username, realm, nonce, uri, qop, nonce_count, cnonce, response, opaque_kv ); msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); if (!send_line_crlf (sd, buf)) goto error; if (!send_crlf (sd)) goto error; /* receive reply from proxy */ if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) goto error; /* remove trailing CR, LF */ chomp (buf); msg (D_PROXY, "HTTP proxy returned: '%s'", buf); /* parse return string */ nparms = sscanf (buf, "%*s %d", &status); processed = true; } else { msg (D_PROXY, "HTTP proxy: digest method not supported"); goto error; } } #endif else if (p->options.auth_retry) { /* figure out what kind of authentication the proxy needs */ char *pa = NULL; const int method = get_proxy_authenticate(sd, p->options.timeout, &pa, NULL, signal_received); if (method != HTTP_AUTH_NONE) { if (pa) msg (D_PROXY, "HTTP proxy authenticate '%s'", pa); if (p->options.auth_retry == PAR_NCT && method == HTTP_AUTH_BASIC) { msg (D_PROXY, "HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled"); goto error; } p->auth_method = method; store_proxy_authenticate(p, pa); ret = true; goto done; } else { msg (D_PROXY, "HTTP proxy: do not recognize the authentication method required by proxy"); free (pa); goto error; } } else { if (!processed) msg (D_PROXY, "HTTP proxy: no support for proxy authentication method"); goto error; } /* clear state */ if (p->options.auth_retry) clear_user_pass_http(); store_proxy_authenticate(p, NULL); } /* check return code, success = 200 */ if (nparms < 1 || status != 200) { msg (D_LINK_ERRORS, "HTTP proxy returned bad status"); #if 0 /* DEBUGGING -- show a multi-line HTTP error response */ dump_residual(sd, p->options.timeout, signal_received); #endif goto error; } /* SUCCESS */ /* receive line from proxy and discard */ if (!recv_line (sd, NULL, 0, p->options.timeout, true, NULL, signal_received)) goto error; /* * Toss out any extraneous chars, but don't throw away the * start of the OpenVPN data stream (put it in lookahead). */ while (recv_line (sd, NULL, 0, 2, false, lookahead, signal_received)) ; /* reset queried_creds so that we don't think that the next creds request is due to an auth error */ p->queried_creds = false; #if 0 if (lookahead && BLEN (lookahead)) msg (M_INFO, "HTTP PROXY: lookahead: %s", format_hex (BPTR (lookahead), BLEN (lookahead), 0)); #endif done: gc_free (&gc); return ret; error: /* on error, should we exit or restart? */ if (!*signal_received) *signal_received = (p->options.retry ? SIGUSR1 : SIGTERM); /* SOFT-SIGUSR1 -- HTTP proxy error */ gc_free (&gc); return ret; }
bool tls_crypt_unwrap(const struct buffer *src, struct buffer *dst, struct crypto_options *opt) { static const char error_prefix[] = "tls-crypt unwrap error"; const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt; struct gc_arena gc; gc_init(&gc); ASSERT(opt); ASSERT(src->len > 0); ASSERT(ctx->cipher); ASSERT(packet_id_initialized(&opt->packet_id) || (opt->flags & CO_IGNORE_PACKET_ID)); dmsg(D_PACKET_CONTENT, "TLS-CRYPT UNWRAP FROM: %s", format_hex(BPTR(src), BLEN(src), 80, &gc)); if (buf_len(src) < TLS_CRYPT_OFF_CT) { CRYPT_ERROR("packet too short"); } /* Decrypt cipher text */ { int outlen = 0; /* Buffer overflow check (should never fail) */ if (!buf_safe(dst, BLEN(src) - TLS_CRYPT_OFF_CT + TLS_CRYPT_BLOCK_SIZE)) { CRYPT_ERROR("potential buffer overflow"); } if (!cipher_ctx_reset(ctx->cipher, BPTR(src) + TLS_CRYPT_OFF_TAG)) { CRYPT_ERROR("cipher reset failed"); } if (!cipher_ctx_update(ctx->cipher, BPTR(dst), &outlen, BPTR(src) + TLS_CRYPT_OFF_CT, BLEN(src) - TLS_CRYPT_OFF_CT)) { CRYPT_ERROR("cipher update failed"); } ASSERT(buf_inc_len(dst, outlen)); if (!cipher_ctx_final(ctx->cipher, BPTR(dst), &outlen)) { CRYPT_ERROR("cipher final failed"); } ASSERT(buf_inc_len(dst, outlen)); } /* Check authentication */ { const uint8_t *tag = BPTR(src) + TLS_CRYPT_OFF_TAG; uint8_t tag_check[TLS_CRYPT_TAG_SIZE] = { 0 }; dmsg(D_PACKET_CONTENT, "TLS-CRYPT UNWRAP AD: %s", format_hex(BPTR(src), TLS_CRYPT_OFF_TAG, 0, &gc)); dmsg(D_PACKET_CONTENT, "TLS-CRYPT UNWRAP TO: %s", format_hex(BPTR(dst), BLEN(dst), 80, &gc)); hmac_ctx_reset(ctx->hmac); hmac_ctx_update(ctx->hmac, BPTR(src), TLS_CRYPT_OFF_TAG); hmac_ctx_update(ctx->hmac, BPTR(dst), BLEN(dst)); hmac_ctx_final(ctx->hmac, tag_check); if (memcmp_constant_time(tag, tag_check, sizeof(tag_check))) { dmsg(D_CRYPTO_DEBUG, "tag : %s", format_hex(tag, sizeof(tag_check), 0, &gc)); dmsg(D_CRYPTO_DEBUG, "tag_check: %s", format_hex(tag_check, sizeof(tag_check), 0, &gc)); CRYPT_ERROR("packet authentication failed"); } } /* Check replay */ if (!(opt->flags & CO_IGNORE_PACKET_ID)) { struct packet_id_net pin; struct buffer tmp = *src; ASSERT(buf_advance(&tmp, TLS_CRYPT_OFF_PID)); ASSERT(packet_id_read(&pin, &tmp, true)); if (!crypto_check_replay(opt, &pin, error_prefix, &gc)) { CRYPT_ERROR("packet replay"); } } gc_free(&gc); return true; error_exit: crypto_clear_error(); dst->len = 0; gc_free(&gc); return false; }
bool tls_crypt_wrap(const struct buffer *src, struct buffer *dst, struct crypto_options *opt) { const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt; struct gc_arena gc; /* IV, packet-ID and implicit IV required for this mode. */ ASSERT(ctx->cipher); ASSERT(ctx->hmac); ASSERT(packet_id_initialized(&opt->packet_id)); ASSERT(hmac_ctx_size(ctx->hmac) == 256/8); gc_init(&gc); dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP FROM: %s", format_hex(BPTR(src), BLEN(src), 80, &gc)); /* Get packet ID */ if (!packet_id_write(&opt->packet_id.send, dst, true, false)) { msg(D_CRYPT_ERRORS, "TLS-CRYPT ERROR: packet ID roll over."); goto err; } dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP AD: %s", format_hex(BPTR(dst), BLEN(dst), 0, &gc)); /* Buffer overflow check */ if (!buf_safe(dst, BLEN(src) + TLS_CRYPT_BLOCK_SIZE + TLS_CRYPT_TAG_SIZE)) { msg(D_CRYPT_ERRORS, "TLS-CRYPT WRAP: buffer size error, " "sc=%d so=%d sl=%d dc=%d do=%d dl=%d", src->capacity, src->offset, src->len, dst->capacity, dst->offset, dst->len); goto err; } /* Calculate auth tag and synthetic IV */ { uint8_t *tag = NULL; hmac_ctx_reset(ctx->hmac); hmac_ctx_update(ctx->hmac, BPTR(dst), BLEN(dst)); hmac_ctx_update(ctx->hmac, BPTR(src), BLEN(src)); ASSERT(tag = buf_write_alloc(dst, TLS_CRYPT_TAG_SIZE)); hmac_ctx_final(ctx->hmac, tag); dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP TAG: %s", format_hex(tag, TLS_CRYPT_TAG_SIZE, 0, &gc)); /* Use the 128 most significant bits of the tag as IV */ ASSERT(cipher_ctx_reset(ctx->cipher, tag)); } /* Encrypt src */ { int outlen = 0; ASSERT(cipher_ctx_update(ctx->cipher, BEND(dst), &outlen, BPTR(src), BLEN(src))); ASSERT(buf_inc_len(dst, outlen)); ASSERT(cipher_ctx_final(ctx->cipher, BPTR(dst), &outlen)); ASSERT(buf_inc_len(dst, outlen)); } dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP TO: %s", format_hex(BPTR(dst), BLEN(dst), 80, &gc)); gc_free(&gc); return true; err: crypto_clear_error(); dst->len = 0; gc_free(&gc); return false; }
const char * session_id_print (const struct session_id *sid, struct gc_arena *gc) { return format_hex (sid->id, SID_SIZE, 0, gc); }
/* * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet. * * Set buf->len to 0 and return false on decrypt error. * * On success, buf is set to point to plaintext, true * is returned. */ bool openvpn_decrypt (struct buffer *buf, struct buffer work, const struct crypto_options *opt, const struct frame* frame) { static const char error_prefix[] = "Authenticate/Decrypt packet error"; struct gc_arena gc; gc_init (&gc); if (buf->len > 0 && opt->key_ctx_bi) { struct key_ctx *ctx = &opt->key_ctx_bi->decrypt; struct packet_id_net pin; bool have_pin = false; /* Verify the HMAC */ if (ctx->hmac) { int hmac_len; uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ hmac_ctx_reset(ctx->hmac); /* Assume the length of the input HMAC */ hmac_len = hmac_ctx_size (ctx->hmac); /* Authentication fails if insufficient data in packet for HMAC */ if (buf->len < hmac_len) CRYPT_ERROR ("missing authentication info"); hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len, BLEN (buf) - hmac_len); hmac_ctx_final (ctx->hmac, local_hmac); /* Compare locally computed HMAC with packet HMAC */ if (memcmp_constant_time (local_hmac, BPTR (buf), hmac_len)) CRYPT_ERROR ("packet HMAC authentication failed"); ASSERT (buf_advance (buf, hmac_len)); } /* Decrypt packet ID + payload */ if (ctx->cipher) { const int iv_size = cipher_ctx_iv_length (ctx->cipher); const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher); uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH]; int outlen; /* initialize work buffer with FRAME_HEADROOM bytes of prepend capacity */ ASSERT (buf_init (&work, FRAME_HEADROOM_ADJ (frame, FRAME_HEADROOM_MARKER_DECRYPT))); /* use IV if user requested it */ CLEAR (iv_buf); if (opt->flags & CO_USE_IV) { if (buf->len < iv_size) CRYPT_ERROR ("missing IV info"); memcpy (iv_buf, BPTR (buf), iv_size); ASSERT (buf_advance (buf, iv_size)); } /* show the IV's initial state */ if (opt->flags & CO_USE_IV) dmsg (D_PACKET_CONTENT, "DECRYPT IV: %s", format_hex (iv_buf, iv_size, 0, &gc)); if (buf->len < 1) CRYPT_ERROR ("missing payload"); /* ctx->cipher was already initialized with key & keylen */ if (!cipher_ctx_reset (ctx->cipher, iv_buf)) CRYPT_ERROR ("cipher init failed"); /* Buffer overflow check (should never happen) */ if (!buf_safe (&work, buf->len + cipher_ctx_block_size(ctx->cipher))) CRYPT_ERROR ("potential buffer overflow"); /* Decrypt packet ID, payload */ if (!cipher_ctx_update (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf))) CRYPT_ERROR ("cipher update failed"); ASSERT (buf_inc_len(&work, outlen)); /* Flush the decryption buffer */ if (!cipher_ctx_final (ctx->cipher, BPTR (&work) + outlen, &outlen)) CRYPT_ERROR ("cipher final failed"); ASSERT (buf_inc_len(&work, outlen)); dmsg (D_PACKET_CONTENT, "DECRYPT TO: %s", format_hex (BPTR (&work), BLEN (&work), 80, &gc)); /* Get packet ID from plaintext buffer or IV, depending on cipher mode */ { if (cipher_kt_mode_cbc(cipher_kt)) { if (opt->packet_id) { if (!packet_id_read (&pin, &work, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM))) CRYPT_ERROR ("error reading CBC packet-id"); have_pin = true; } } else if (cipher_kt_mode_ofb_cfb(cipher_kt)) { struct buffer b; ASSERT (opt->flags & CO_USE_IV); /* IV and packet-ID required */ ASSERT (opt->packet_id); /* for this mode. */ buf_set_read (&b, iv_buf, iv_size); if (!packet_id_read (&pin, &b, true)) CRYPT_ERROR ("error reading CFB/OFB packet-id"); have_pin = true; } else /* We only support CBC, CFB, or OFB modes right now */ { ASSERT (0); } } } else { work = *buf; if (opt->packet_id) { if (!packet_id_read (&pin, &work, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM))) CRYPT_ERROR ("error reading packet-id"); have_pin = !BOOL_CAST (opt->flags & CO_IGNORE_PACKET_ID); } } if (have_pin) { packet_id_reap_test (&opt->packet_id->rec); if (packet_id_test (&opt->packet_id->rec, &pin)) { packet_id_add (&opt->packet_id->rec, &pin); if (opt->pid_persist && (opt->flags & CO_PACKET_ID_LONG_FORM)) packet_id_persist_save_obj (opt->pid_persist, opt->packet_id); } else { if (!(opt->flags & CO_MUTE_REPLAY_WARNINGS)) msg (D_REPLAY_ERRORS, "%s: bad packet ID (may be a replay): %s -- see the man page entry for --no-replay and --replay-window for more info or silence this warning with --mute-replay-warnings", error_prefix, packet_id_net_print (&pin, true, &gc)); goto error_exit; } } *buf = work; } gc_free (&gc); return true; error_exit: crypto_clear_error(); buf->len = 0; gc_free (&gc); return false; }
bool establish_http_proxy_passthru (struct http_proxy_info *p, socket_descriptor_t sd, /* already open to proxy */ const char *host, /* openvpn server remote */ const int port, /* openvpn server port */ struct buffer *lookahead, volatile int *signal_received) { struct gc_arena gc = gc_new (); char buf[256]; char buf2[128]; char get[80]; int status; int nparms; bool ret = false; /* get user/pass if not previously given or if --auto-proxy is being used */ if (p->auth_method == HTTP_AUTH_BASIC || p->auth_method == HTTP_AUTH_NTLM) get_user_pass_http (p, false); /* format HTTP CONNECT message */ openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s\r\nHOST: %s:%d", host, port, p->options.http_version, host, port); msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); /* send HTTP CONNECT message to proxy */ if (!send_line_crlf (sd, buf)) goto error; /* send User-Agent string if provided */ if (p->options.user_agent) { openvpn_snprintf (buf, sizeof(buf), "User-Agent: %s", p->options.user_agent); if (!send_line_crlf (sd, buf)) goto error; } /* auth specified? */ switch (p->auth_method) { case HTTP_AUTH_NONE: break; case HTTP_AUTH_BASIC: openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Basic %s", username_password_as_base64 (p, &gc)); msg (D_PROXY, "Attempting Basic Proxy-Authorization"); dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf); openvpn_sleep (1); if (!send_line_crlf (sd, buf)) goto error; break; #if NTLM case HTTP_AUTH_NTLM: case HTTP_AUTH_NTLM2: /* keep-alive connection */ openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive"); if (!send_line_crlf (sd, buf)) goto error; openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s", ntlm_phase_1 (p, &gc)); msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 1"); dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf); openvpn_sleep (1); if (!send_line_crlf (sd, buf)) goto error; break; #endif default: ASSERT (0); } /* send empty CR, LF */ openvpn_sleep (1); if (!send_crlf (sd)) goto error; /* receive reply from proxy */ if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) goto error; /* remove trailing CR, LF */ chomp (buf); msg (D_PROXY, "HTTP proxy returned: '%s'", buf); /* parse return string */ nparms = sscanf (buf, "%*s %d", &status); /* check for a "407 Proxy Authentication Required" response */ if (nparms >= 1 && status == 407) { msg (D_PROXY, "Proxy requires authentication"); /* check for NTLM */ if (p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) { #if NTLM /* look for the phase 2 response */ while (true) { if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) goto error; chomp (buf); msg (D_PROXY, "HTTP proxy returned: '%s'", buf); openvpn_snprintf (get, sizeof get, "%%*s NTLM %%%ds", (int) sizeof (buf2) - 1); nparms = sscanf (buf, get, buf2); buf2[127] = 0; /* we only need the beginning - ensure it's null terminated. */ /* check for "Proxy-Authenticate: NTLM TlRM..." */ if (nparms == 1) { /* parse buf2 */ msg (D_PROXY, "auth string: '%s'", buf2); break; } } /* if we are here then auth string was got */ msg (D_PROXY, "Received NTLM Proxy-Authorization phase 2 response"); /* receive and discard everything else */ while (recv_line (sd, NULL, 0, p->options.timeout, true, NULL, signal_received)) ; /* now send the phase 3 reply */ /* format HTTP CONNECT message */ openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s", host, port, p->options.http_version); msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); /* send HTTP CONNECT message to proxy */ if (!send_line_crlf (sd, buf)) goto error; /* keep-alive connection */ openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive"); if (!send_line_crlf (sd, buf)) goto error; /* send HOST etc, */ openvpn_sleep (1); openvpn_snprintf (buf, sizeof(buf), "Host: %s", host); msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); if (!send_line_crlf (sd, buf)) goto error; msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 3"); { const char *np3 = ntlm_phase_3 (p, buf2, &gc); if (!np3) { msg (D_PROXY, "NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server"); goto error; } openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s", np3); } msg (D_PROXY, "Send to HTTP proxy: '%s'", buf); openvpn_sleep (1); if (!send_line_crlf (sd, buf)) goto error; /* ok so far... */ /* send empty CR, LF */ openvpn_sleep (1); if (!send_crlf (sd)) goto error; /* receive reply from proxy */ if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) goto error; /* remove trailing CR, LF */ chomp (buf); msg (D_PROXY, "HTTP proxy returned: '%s'", buf); /* parse return string */ nparms = sscanf (buf, "%*s %d", &status); #else ASSERT (0); /* No NTLM support */ #endif } else if (p->auth_method == HTTP_AUTH_NONE && p->options.auth_retry) { /* * Proxy needs authentication, but we don't have a user/pass. * Now we will change p->auth_method and return true so that * our caller knows to call us again on a newly opened socket. * JYFIXME: This code needs to check proxy error output and set * JYFIXME: p->auth_method = HTTP_AUTH_NTLM if necessary. */ p->auth_method = HTTP_AUTH_BASIC; ret = true; goto done; } else goto error; } /* check return code, success = 200 */ if (nparms < 1 || status != 200) { msg (D_LINK_ERRORS, "HTTP proxy returned bad status"); #if 0 /* DEBUGGING -- show a multi-line HTTP error response */ while (true) { if (!recv_line (sd, buf, sizeof (buf), p->options.timeout, true, NULL, signal_received)) goto error; chomp (buf); msg (D_PROXY, "HTTP proxy returned: '%s'", buf); } #endif goto error; } /* receive line from proxy and discard */ if (!recv_line (sd, NULL, 0, p->options.timeout, true, NULL, signal_received)) goto error; /* * Toss out any extraneous chars, but don't throw away the * start of the OpenVPN data stream (put it in lookahead). */ while (recv_line (sd, NULL, 0, 2, false, lookahead, signal_received)) ; #if 0 if (lookahead && BLEN (lookahead)) msg (M_INFO, "HTTP PROXY: lookahead: %s", format_hex (BPTR (lookahead), BLEN (lookahead), 0)); #endif done: gc_free (&gc); return ret; error: /* on error, should we exit or restart? */ if (!*signal_received) *signal_received = (p->options.retry ? SIGUSR1 : SIGTERM); /* SOFT-SIGUSR1 -- HTTP proxy error */ gc_free (&gc); return ret; }
static int archive_write_newc_header(struct archive_write *a, struct archive_entry *entry) { struct cpio *cpio; const char *p, *path; int pathlength, ret; struct cpio_header_newc h; int pad; cpio = (struct cpio *)a->format_data; ret = 0; path = archive_entry_pathname(entry); pathlength = strlen(path) + 1; /* Include trailing null. */ memset(&h, 0, sizeof(h)); format_hex(0x070701, &h.c_magic, sizeof(h.c_magic)); format_hex(archive_entry_devmajor(entry), &h.c_devmajor, sizeof(h.c_devmajor)); format_hex(archive_entry_devminor(entry), &h.c_devminor, sizeof(h.c_devminor)); if (archive_entry_ino64(entry) > 0xffffffff) { archive_set_error(&a->archive, ERANGE, "large inode number truncated"); ret = ARCHIVE_WARN; } format_hex(archive_entry_ino64(entry) & 0xffffffff, &h.c_ino, sizeof(h.c_ino)); format_hex(archive_entry_mode(entry), &h.c_mode, sizeof(h.c_mode)); format_hex(archive_entry_uid(entry), &h.c_uid, sizeof(h.c_uid)); format_hex(archive_entry_gid(entry), &h.c_gid, sizeof(h.c_gid)); format_hex(archive_entry_nlink(entry), &h.c_nlink, sizeof(h.c_nlink)); if (archive_entry_filetype(entry) == AE_IFBLK || archive_entry_filetype(entry) == AE_IFCHR) { format_hex(archive_entry_rdevmajor(entry), &h.c_rdevmajor, sizeof(h.c_rdevmajor)); format_hex(archive_entry_rdevminor(entry), &h.c_rdevminor, sizeof(h.c_rdevminor)); } else { format_hex(0, &h.c_rdevmajor, sizeof(h.c_rdevmajor)); format_hex(0, &h.c_rdevminor, sizeof(h.c_rdevminor)); } format_hex(archive_entry_mtime(entry), &h.c_mtime, sizeof(h.c_mtime)); format_hex(pathlength, &h.c_namesize, sizeof(h.c_namesize)); format_hex(0, &h.c_checksum, sizeof(h.c_checksum)); /* Non-regular files don't store bodies. */ if (archive_entry_filetype(entry) != AE_IFREG) archive_entry_set_size(entry, 0); /* Symlinks get the link written as the body of the entry. */ p = archive_entry_symlink(entry); if (p != NULL && *p != '\0') format_hex(strlen(p), &h.c_filesize, sizeof(h.c_filesize)); else format_hex(archive_entry_size(entry), &h.c_filesize, sizeof(h.c_filesize)); ret = (a->compressor.write)(a, &h, sizeof(h)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); /* Pad pathname to even length. */ ret = (a->compressor.write)(a, path, pathlength); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); pad = PAD4(pathlength + sizeof(struct cpio_header_newc)); if (pad) ret = (a->compressor.write)(a, "\0\0\0", pad); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); cpio->entry_bytes_remaining = archive_entry_size(entry); cpio->padding = PAD4(cpio->entry_bytes_remaining); /* Write the symlink now. */ if (p != NULL && *p != '\0') { ret = (a->compressor.write)(a, p, strlen(p)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); pad = PAD4(strlen(p)); ret = (a->compressor.write)(a, "\0\0\0", pad); } return (ret); }
int dataman_process_keep_alive(struct netconn *nc, uint8_t *rawmsg, int len) { struct dataman * dm = (struct dataman *)(nc->data); uint8_t *msgptr = rawmsg + cw_get_hdr_msg_offset(rawmsg); int elems_len = cw_get_datamsg_elems_len(msgptr); uint8_t * elems_ptr = cw_get_datamsg_elems_ptr(msgptr); uint8_t * elem; cw_foreach_elem(elem, elems_ptr, elems_len) { if (cw_get_elem_id(elem) == CW_ELEM_SESSION_ID){ uint8_t sessid[16]; memset(sessid,0,16); int sessid_len = cw_get_elem_len(elem); printf("Sess id len = %d\n",sessid_len); memcpy(sessid,cw_get_elem_data(elem),sessid_len); struct wtpman * wtpman = wtplist_get_by_session_id(sessid); if (wtpman){ if (!dm->wtpman) dm->wtpman=wtpman; uint8_t buffer[128]; uint8_t * dl = cw_init_data_keep_alive_msg(buffer,NULL); uint8_t * d=dl+2; int l = cw_put_elem_session_id(d,sessid,sessid_len); cw_put_word(dl,l); int total_len = dl-buffer + l+2; printf("len len %d\n",l); printf("Total len = %d\n",total_len); netconn_send_capwap_msg(nc,buffer,total_len); return len; printf("Found!i yes I vae found it\n"); } int l = cw_get_elem_len(elem); printf("ElemID: %d, len = %d\n", cw_get_elem_id(elem),l); char cb[64]; format_hex(cb,sessid,16); printf("Session ID: %s",cb); } } errno=EAGAIN; return -1; }
bool format(const DistributedType* dtype) { Type type = dtype->get_type(); switch(type) { case T_INVALID: { out << "<invalid>"; break; } case T_INT8: { if(!remaining(sizeof(int8_t))) { return false; } int v = *(int8_t*)(in + offset); offset += sizeof(int8_t); out << v; break; } case T_INT16: { if(!remaining(sizeof(int16_t))) { return false; } int v = swap_le(*(int16_t*)(in + offset)); offset += sizeof(int16_t); out << v; break; } case T_INT32: { if(!remaining(sizeof(int32_t))) { return false; } int v = swap_le(*(int32_t*)(in + offset)); offset += sizeof(int32_t); out << v; break; } case T_INT64: { if(!remaining(sizeof(int64_t))) { return false; } int64_t v = swap_le(*(int64_t*)(in + offset)); offset += sizeof(int64_t); out << v; break; } case T_UINT8: { if(!remaining(sizeof(uint8_t))) { return false; } unsigned int v = *(uint8_t*)(in + offset); offset += sizeof(uint8_t); out << v; break; } case T_UINT16: { if(!remaining(sizeof(uint16_t))) { return false; } unsigned int v = swap_le(*(uint16_t*)(in + offset)); offset += sizeof(uint16_t); out << v; break; } case T_UINT32: { if(!remaining(sizeof(uint32_t))) { return false; } unsigned int v = swap_le(*(uint32_t*)(in + offset)); offset += sizeof(uint32_t); out << v; break; } case T_UINT64: { if(!remaining(sizeof(uint64_t))) { return false; } uint64_t v = swap_le(*(uint64_t*)(in + offset)); offset += sizeof(uint64_t); out << v; break; } case T_FLOAT32: { if(!remaining(sizeof(float))) { return false; } float v = (float)swap_le(*(float*)(in + offset)); offset += sizeof(float); out << v; break; } case T_FLOAT64: { if(!remaining(sizeof(double))) { return false; } double v = (double)swap_le(*(double*)(in + offset)); offset += sizeof(double); out << v; break; } case T_CHAR: { if(!remaining(sizeof(char))) { return false; } char v = *(char*)(in + offset); format_quoted('\'', string(1, v), out); offset += sizeof(char); break; } case T_STRING: { // Read string length sizetag_t length = dtype->get_size(); // If we have a string alias format as a quoted string if(dtype->has_alias() && dtype->get_alias() == "string") { // Read string if(!remaining(length)) { return false; } string str((const char*)in + offset, length); offset += length; // Enquoute and escape string then output format_quoted('"', str, out); } else { // Otherwise format as an array of char out << '['; const ArrayType* arr = dtype->as_array(); bool ok = format(arr->get_element_type()); if(!ok) { return false; } for(unsigned int i = 1; i < arr->get_array_size(); ++i) { out << ", "; ok = format(arr->get_element_type()); if(!ok) { return false; } } out << ']'; } break; } case T_VARSTRING: { // If we have a string alias format as a quoted string if(dtype->has_alias() && dtype->get_alias() == "string") { // Read string length if(!remaining(sizeof(sizetag_t))) { return false; } sizetag_t length = read_length(); // Read string if(!remaining(length)) { return false; } string str((const char*)in + offset, length); offset += length; // Enquoute and escape string then output format_quoted('"', str, out); } else { // Otherwise format as an array of char out << '['; // Read array byte length if(!remaining(sizeof(sizetag_t))) { out << ']'; return false; } sizetag_t length = read_length(); if(length == 0) { out << ']'; break; } // Read array if(!remaining(length)) { out << ']'; return false; } size_t array_end = offset + length; const ArrayType* arr = dtype->as_array(); bool ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } while(offset < array_end) { out << ", "; ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } } // Check to make sure we didn't overshoot the array while reading if(offset > array_end) { out << ']'; return false; } out << ']'; } break; } case T_BLOB: { // Read blob length sizetag_t length = dtype->get_size(); // If we have a blob alias format as a hex constant if(dtype->has_alias() && dtype->get_alias() == "blob") { // Read blob if(!remaining(length)) { return false; } string blob((const char*)in + offset, length); offset += length; // Format blob as a hex constant then output format_hex(blob, out); } else { // Otherwise format as an array of uint8 out << '['; const ArrayType* arr = dtype->as_array(); bool ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } for(unsigned int i = 1; i < arr->get_array_size(); ++i) { out << ", "; ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } } out << ']'; } break; } case T_VARBLOB: { // If we have a blob alias format as a hex constant if(dtype->has_alias() && dtype->get_alias() == "blob") { // Read blob length if(!remaining(sizeof(sizetag_t))) { return false; } sizetag_t length = read_length(); // Read blob with length if(!remaining(length)) { return false; } string blob((const char*)in + offset - 2, length + 2); offset += length; // Format blob and length as a hex constant then output format_hex(blob, out); } else { // Otherwise format as an array of uint8 out << '['; // Read array byte length if(!remaining(sizeof(sizetag_t))) { out << ']'; return false; } sizetag_t length = read_length(); if(length == 0) { out << ']'; break; } // Read array if(!remaining(length)) { out << ']'; return false; } size_t array_end = offset + length; const ArrayType* arr = dtype->as_array(); bool ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } while(offset < array_end) { out << ", "; ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } } // Check to make sure we didn't overshoot the array while reading if(offset > array_end) { out << ']'; return false; } out << ']'; } break; } case T_ARRAY: { out << '['; const ArrayType* arr = dtype->as_array(); bool ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } for(unsigned int i = 1; i < arr->get_array_size(); ++i) { out << ", "; ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } } out << ']'; break; } case T_VARARRAY: { out << '['; // Read array byte length if(!remaining(sizeof(sizetag_t))) { out << ']'; return false; } sizetag_t length = read_length(); if(length == 0) { out << ']'; break; } // Read array if(!remaining(length)) { out << ']'; return false; } size_t array_end = offset + length; const ArrayType* arr = dtype->as_array(); bool ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } while(offset < array_end) { out << ", "; ok = format(arr->get_element_type()); if(!ok) { out << ']'; return false; } } // Check to make sure we didn't overshoot the array while reading if(offset > array_end) { out << ']'; return false; } out << ']'; break; } case T_STRUCT: { out << '{'; const Struct* strct = dtype->as_struct(); size_t num_fields = strct->get_num_fields(); if(num_fields > 0) { bool ok = format(strct->get_field(0)->get_type()); if(!ok) { out << '}'; return false; } for(unsigned int i = 1; i < num_fields; ++i) { out << ", "; ok = format(strct->get_field(i)->get_type()); if(!ok) { out << '}'; return false; } } } out << '}'; break; } case T_METHOD: { out << '('; const Method* method = dtype->as_method(); size_t num_params = method->get_num_parameters(); if(num_params > 0) { bool ok = format(method->get_parameter(0)->get_type()); if(!ok) { out << ')'; return false; } for(unsigned int i = 1; i < num_params; ++i) { out << ", "; ok = format(method->get_parameter(i)->get_type()); if(!ok) { out << ')'; return false; } } } out << ')'; break; } default: { out << "<error>"; return false; } } return true; }
string format_hex(const string &str) { ostringstream ss; format_hex(str, ss); return ss.str(); }
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; }