b43-fwcutter-011/000075500000000000000000000000001103557476600136225ustar00rootroot00000000000000b43-fwcutter-011/Makefile000064400000000000000000000012241103557476600152610ustar00rootroot00000000000000VERSION = 011 CC ?= cc PREFIX ?= /usr/local CFLAGS ?= -Os -fomit-frame-pointer CFLAGS += -std=c99 -Wall -pedantic -D_BSD_SOURCE LDFLAGS ?= OBJECTS = fwcutter.o md5.o BIN = b43-fwcutter CFLAGS += -DFWCUTTER_VERSION_=$(VERSION) all: $(BIN) fwcutter.o: fwcutter.h fwcutter_list.h md5.h md5.o: md5.h $(BIN): $(OBJECTS) $(CC) $(CFLAGS) -o $(BIN) $(OBJECTS) $(LDFLAGS) install: all -install -d -o 0 -g 0 -m 755 $(PREFIX)/bin/ -install -o 0 -g 0 -m 755 $(BIN) $(PREFIX)/bin/ -install -d -o 0 -g 0 -m 755 $(PREFIX)/man/man1/ -install -o 0 -g 0 -m 644 $(BIN).1 $(PREFIX)/man/man1/ clean: -rm -f *.o $(BIN) distclean: clean -rm -f *.fw *.orig *.rej *~ b43-fwcutter-011/README000064400000000000000000000033021103557476600145000ustar00rootroot00000000000000 BCM43XX Linux Driver Project ============================ About this software ------------------- b43-fwcutter is a tool which can extract firmware from various source files. It's written for BCM43xx driver files. The project page is http://bcm43xx.berlios.de/ Usage ----- b43-fwcutter FILE extracts the firmware from a source FILE to the current directory, creating a directory "b43" or "b43legacy" with files in it. b43-fwcutter -i FILE identify the driver file; print information but don't extract. b43-fwcutter -w /tmp FILE extract and write firmware to /tmp. b43-fwcutter -l prints a list of supported driver source files. After extraction, copy the "b43" or "b43legacy" directory to your firmware directory (usually /lib/firmware or similar, see below). Alternatively you can use the -w option to b43-fwcutter. Different distributions use different directories to load firmware from. If the driver complains about missing firmware files look for the correct directory. For some distributions you have to use /lib/hotplug/firmware or /usr/lib/hotplug/firmware but other directories are also possible. Because firmware file are stored in big endian, extraction doesn't depend on the system you're using. You can use extracted firmware from any driver on any system and also copy the extracted files to any other system (e.g. if extraction on the target system isn't feasible.) Where can I find some driver source files? ------------------------------------------ Please check the references at http://www.linuxwireless.org/en/users/Drivers/bcm43xx#devicefirmware It is recommended that you extract firmware for both b43 and b43legacy in order to support both types of cards on your system. b43-fwcutter-011/b43-fwcutter.1000064400000000000000000000022351103557476600161370ustar00rootroot00000000000000.\" Initially generated by help2man 1.36. .TH B43-FWCUTTER "1" "2007" "b43-fwcutter" "User Commands" .SH NAME b43-fwcutter \- manual page for b43-fwcutter .SH SYNOPSIS .B b43-fwcutter [\fIOPTION\fR] [\fIDRIVER\fR] .SH DESCRIPTION b43-fwcutter can extract the firmware for your Broadcom 43xx hardware from different closed source drivers. The b43 driver depends on this firmware files and can't work without them. .PP Currently b43-fwcutter supports Apple MacOS X, Microsoft Windows 98/ME/2000/XP and Linux drivers, but keep in mind that b43-fwcutter doesn't support all driver versions. .PP Example: .IP b43-fwcutter bcmwl5.sys .PP to cut the firmware out of bcmwl5.sys .SH OPTIONS .TP \fB\-l\fR|\-\-list List supported driver versions .TP \fB\-i\fR|\-\-identify Only identify the driver file (don't extract) .TP \fB\-w\fR|\-\-target\-dir DIR Extract and write firmware to DIR .TP \fB\-a\fR|\-\-alt\-iv Extract alternative initvals (only 3.10.x.x) .TP \fB\-p\fR|\-\-postfix ".FOO" Postfix for firmware filenames (.FOO.fw) .TP \fB\-v\fR|\-\-version Print b43-fwcutter version .TP \fB\-h\fR|\-\-help Print help information .SH AUTHORS b43 development team, http://bcm43xx.berlios.de b43-fwcutter-011/fwcutter.c000064400000000000000000000420031103557476600156300ustar00rootroot00000000000000/* * firmware cutter for broadcom 43xx wireless driver files * * Copyright (c) 2005 Martin Langer , * 2005-2007 Michael Buesch * 2005 Alex Beregszaszi * 2007 Johannes Berg * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #ifdef __DragonFly__ #include #else #include #endif #include "md5.h" #include "fwcutter.h" #include "fwcutter_list.h" #ifdef __DragonFly__ #define V3_FW_DIRNAME "v3" #define V4_FW_DIRNAME "v4" #else #define V3_FW_DIRNAME "b43legacy" #define V4_FW_DIRNAME "b43" #endif static struct cmdline_args cmdargs; /* check whether file will be listed/extracted from */ static int file_ok(const struct file *f) { return !(f->flags & FW_FLAG_UNSUPPORTED) || cmdargs.unsupported; } /* Convert a CPU-endian 16bit integer to Big-Endian */ static be16_t to_be16(uint16_t v) { uint8_t ret[2]; ret[0] = (v & 0xFF00) >> 8; ret[1] = (v & 0x00FF); return *((be16_t *)ret); } #if 0 /* Convert a Big-Endian 16bit integer to CPU-endian */ static uint16_t from_be16(be16_t v) { uint16_t ret = 0; ret |= (uint16_t)(((uint8_t *)&v)[0]) << 8; ret |= (uint16_t)(((uint8_t *)&v)[1]); return ret; } #endif /* Convert a CPU-endian 32bit integer to Big-Endian */ static be32_t to_be32(uint32_t v) { uint8_t ret[4]; ret[0] = (v & 0xFF000000) >> 24; ret[1] = (v & 0x00FF0000) >> 16; ret[2] = (v & 0x0000FF00) >> 8; ret[3] = (v & 0x000000FF); return *((be32_t *)ret); } /* Convert a Big-Endian 32bit integer to CPU-endian */ static uint32_t from_be32(be32_t v) { uint32_t ret = 0; ret |= (uint32_t)(((uint8_t *)&v)[0]) << 24; ret |= (uint32_t)(((uint8_t *)&v)[1]) << 16; ret |= (uint32_t)(((uint8_t *)&v)[2]) << 8; ret |= (uint32_t)(((uint8_t *)&v)[3]); return ret; } /* tiny disassembler */ static void print_ucode_version(struct insn *insn) { int val; /* * The instruction we're looking for is a store to memory * offset insn->op3 of the constant formed like `val' below. * 0x2de00 is the opcode for type 1, 0x378 is the opcode * for type 2 and 3. */ if (insn->opcode != 0x378 && insn->opcode != 0x2de00) return; val = ((0xFF & insn->op1) << 8) | (0xFF & insn->op2); /* * Memory offsets are word-offsets, for the meaning * see http://bcm-v4.sipsolutions.net/802.11/ObjectMemory */ switch (insn->op3) { case 0: printf(" ucode version: %d\n", val); break; case 1: printf(" ucode revision: %d\n", val); break; case 2: printf(" ucode date: %.4d-%.2d-%.2d\n", 2000 + (val >> 12), (val >> 8) & 0xF, val & 0xFF); break; case 3: printf(" ucode time: %.2d:%.2d:%.2d\n", val >> 11, (val >> 5) & 0x3f, val & 0x1f); break; } } static void disasm_ucode_1(uint64_t in, struct insn *out) { /* xxyyyzzz00oooooX -> ooooo Xxx yyy zzz * if we swap the upper and lower 32-bits first it becomes easier: * 00oooooxxxyyyzzz -> ooooo xxx yyy zzz */ in = (in >> 32) | (in << 32); out->op3 = in & 0xFFF; out->op2 = (in >> 12) & 0xFFF; out->op1 = (in >> 24) & 0xFFF; out->opcode = (in >> 36) & 0xFFFFF; /* the rest of the in word should be zero */ } static void disasm_ucode_2(uint64_t in, struct insn *out) { /* xxyyyzzz0000oooX -> ooo Xxx yyy zzz * if we swap the upper and lower 32-bits first it becomes easier: * 0000oooxxxyyyzzz -> ooo xxx yyy zzz */ in = (in >> 32) | (in << 32); out->op3 = in & 0xFFF; out->op2 = (in >> 12) & 0xFFF; out->op1 = (in >> 24) & 0xFFF; out->opcode = (in >> 36) & 0xFFF; /* the rest of the in word should be zero */ } static void disasm_ucode_3(uint64_t in, struct insn *out) { /* * like 2, but each operand has one bit more; appears * to use the same instruction set slightly extended */ in = (in >> 32) | (in << 32); out->op3 = in & 0x1FFF; out->op2 = (in >> 13) & 0x1FFF; out->op1 = (in >> 26) & 0x1FFF; out->opcode = (in >> 39) & 0xFFF; /* the rest of the in word should be zero */ } static void analyse_ucode(int ucode_rev, uint8_t *data, uint32_t len) { uint64_t *insns = (uint64_t*)data; struct insn insn; uint32_t i; for (i=0; ireg = bswap_16(iv->reg); iv->size = bswap_16(iv->size); iv->val = bswap_32(iv->val); } static void build_ivs(struct b43_iv **_out, size_t *_out_size, struct iv *in, size_t in_size, struct fw_header *hdr, uint32_t flags) { struct iv *iv; struct b43_iv *out; uint32_t i; size_t out_size = 0; if (sizeof(struct b43_iv) != 6) { printf("sizeof(struct b43_iv) != 6\n"); exit(255); } out = malloc(in_size); if (!out) { perror("failed to allocate buffer"); exit(1); } *_out = out; for (i = 0; i < in_size / sizeof(*iv); i++, in++) { if (flags & FW_FLAG_LE) swap_endianness_iv(in); /* input-IV is BigEndian */ if (in->reg & to_be16(~FW_IV_OFFSET_MASK)) { printf("Input file IV offset > 0x%X\n", FW_IV_OFFSET_MASK); exit(1); } out->offset_size = in->reg; if (in->size == to_be16(4)) { out->offset_size |= to_be16(FW_IV_32BIT); out->data.d32 = in->val; out_size += sizeof(be16_t) + sizeof(be32_t); out = (struct b43_iv *)((uint8_t *)out + sizeof(be16_t) + sizeof(be32_t)); } else if (in->size == to_be16(2)) { if (in->val & to_be32(~0xFFFF)) { printf("Input file 16bit IV value overflow\n"); exit(1); } out->data.d16 = to_be16(from_be32(in->val)); out_size += sizeof(be16_t) + sizeof(be16_t); out = (struct b43_iv *)((uint8_t *)out + sizeof(be16_t) + sizeof(be16_t)); } else { printf("Input file IV size != 2|4\n"); exit(1); } } hdr->size = to_be32(i); *_out_size = out_size; } static void write_file(const char *name, uint8_t *buf, uint32_t len, const struct fw_header *hdr, uint32_t flags) { FILE *f; char nbuf[4096]; const char *dir; int r; if (flags & FW_FLAG_V4) dir = V4_FW_DIRNAME; else dir = V3_FW_DIRNAME; r = snprintf(nbuf, sizeof(nbuf), "%s/%s", cmdargs.target_dir, dir); if (r >= sizeof(nbuf)) { fprintf(stderr, "name too long"); exit(2); } r = mkdir(nbuf, 0770); if (r && errno != EEXIST) { perror("failed to create output directory"); exit(2); } r = snprintf(nbuf, sizeof(nbuf), "%s/%s/%s.fw", cmdargs.target_dir, dir, name); if (r >= sizeof(nbuf)) { fprintf(stderr, "name too long"); exit(2); } f = fopen(nbuf, "w"); if (!f) { perror("failed to open file"); exit(2); } if (fwrite(hdr, sizeof(*hdr), 1, f) != 1) { perror("failed to write file"); exit(2); } if (fwrite(buf, 1, len, f) != len) { perror("failed to write file"); exit(2); } fclose(f); } static void extract_or_identify(FILE *f, const struct extract *extract, uint32_t flags) { uint8_t *buf; size_t data_length; int ucode_rev = 0; struct fw_header hdr; memset(&hdr, 0, sizeof(hdr)); hdr.ver = FW_HDR_VER; if (fseek(f, extract->offset, SEEK_SET)) { perror("failed to seek on file"); exit(2); } buf = malloc(extract->length); if (!buf) { perror("failed to allocate buffer"); exit(3); } if (fread(buf, 1, extract->length, f) != extract->length) { perror("failed to read complete data"); exit(3); } switch (extract->type) { case EXT_UCODE_3: ucode_rev += 1; case EXT_UCODE_2: ucode_rev += 1; case EXT_UCODE_1: ucode_rev += 1; data_length = extract->length; if (flags & FW_FLAG_LE) swap_endianness_ucode(buf, data_length); analyse_ucode(ucode_rev, buf, data_length); hdr.type = FW_TYPE_UCODE; hdr.size = to_be32(data_length); break; case EXT_PCM: data_length = extract->length; if (flags & FW_FLAG_LE) swap_endianness_pcm(buf, data_length); hdr.type = FW_TYPE_PCM; hdr.size = to_be32(data_length); break; case EXT_IV: { struct b43_iv *ivs; hdr.type = FW_TYPE_IV; build_ivs(&ivs, &data_length, (struct iv *)buf, extract->length, &hdr, flags); free(buf); buf = (uint8_t *)ivs; break; } default: exit(255); } if (cmdargs.mode == FWCM_EXTRACT) write_file(extract->name, buf, data_length, &hdr, flags); free(buf); } static void print_banner(void) { printf("b43-fwcutter version " FWCUTTER_VERSION "\n"); } static void print_file(const struct file *file) { char filename[30]; char shortname[30]; if (file->flags & FW_FLAG_V4) printf(V4_FW_DIRNAME "\t\t"); else printf(V3_FW_DIRNAME "\t"); if (strlen(file->name) > 20) { strncpy(shortname, file->name, 20); shortname[20] = '\0'; snprintf(filename, sizeof(filename), "%s..", shortname); } else strcpy (filename, file->name); printf("%s\t", filename); if (strlen(filename) < 8) printf("\t"); if (strlen(filename) < 16) printf("\t"); printf("%s\t", file->ucode_version); if (strlen(file->ucode_version) < 8) printf("\t"); printf("%s\t", file->id); printf("%s\n", file->md5); } static void print_supported_files(void) { int i; print_banner(); printf("\nExtracting firmware is possible " "from these binary driver files.\n" "The column shows the unique identifier string " "for your firmware.\nYou must select the firmware with the " "same ID as printed by the kernel driver on modprobe.\n" "Note that only recent drivers print such a message on modprobe.\n" "Please read http://linuxwireless.org/en/users/Drivers/b43#devicefirmware\n\n"); printf("\t" "\t\t" "\t" "\t" "\n\n"); /* print for legacy driver first */ for (i = 0; i < FILES; i++) if (file_ok(&files[i]) && !(files[i].flags & FW_FLAG_V4)) print_file(&files[i]); for (i = 0; i < FILES; i++) if (file_ok(&files[i]) && files[i].flags & FW_FLAG_V4) print_file(&files[i]); printf("\n"); } static const struct file *find_file(FILE *fd) { unsigned char buffer[16384], signature[16]; struct MD5Context md5c; char md5sig[33]; int i; MD5Init(&md5c); while ((i = (int) fread(buffer, 1, sizeof(buffer), fd)) > 0) MD5Update(&md5c, buffer, (unsigned) i); MD5Final(signature, &md5c); snprintf(md5sig, sizeof(md5sig), "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x" "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", signature[0], signature[1], signature[2], signature[3], signature[4], signature[5], signature[6], signature[7], signature[8], signature[9], signature[10], signature[11], signature[12], signature[13], signature[14], signature[15]); for (i = 0; i < FILES; ++i) { if (file_ok(&files[i]) && strcasecmp(md5sig, files[i].md5) == 0) { printf("This file is recognised as:\n"); printf(" ID : %s\n", files[i].id); printf(" filename : %s\n", files[i].name); printf(" version : %s\n", files[i].ucode_version); printf(" MD5 : %s\n", files[i].md5); return &files[i]; } } printf("Sorry, the input file is either wrong or " "not supported by b43-fwcutter.\n"); printf("This file has an unknown MD5sum %s.\n", md5sig); return NULL; } static void print_usage(int argc, char *argv[]) { print_banner(); printf("\nA tool to extract firmware for a Broadcom 43xx device\n"); printf("from a proprietary Broadcom 43xx device driver file.\n"); printf("\nUsage: %s [OPTION] [proprietary-driver-file]\n", argv[0]); printf(" --unsupported " "Allow working on extractable but unsupported drivers\n"); printf(" -l|--list " "List supported driver versions\n"); printf(" -i|--identify " "Only identify the driver file (don't extract)\n"); printf(" -w|--target-dir DIR " "Extract and write firmware to DIR\n"); printf(" -v|--version " "Print b43-fwcutter version\n"); printf(" -h|--help " "Print this help\n"); printf("\nExample: %s -w /lib/firmware wl_apsta.o\n" " to extract the firmware blobs from wl_apsta.o and store\n" " the resulting firmware in /lib/firmware\n", argv[0]); } static int do_cmp_arg(char **argv, int *pos, const char *template, int allow_merged, char **param) { char *arg; char *next_arg; size_t arg_len, template_len; arg = argv[*pos]; next_arg = argv[*pos + 1]; arg_len = strlen(arg); template_len = strlen(template); if (param) { /* Maybe we have a merged parameter here. * A merged parameter is "-pfoobar" for example. */ if (allow_merged && arg_len > template_len) { if (memcmp(arg, template, template_len) == 0) { *param = arg + template_len; return ARG_MATCH; } return ARG_NOMATCH; } else if (arg_len != template_len) return ARG_NOMATCH; *param = next_arg; } if (strcmp(arg, template) == 0) { if (param) { /* Skip the parameter on the next iteration. */ (*pos)++; if (!*param) { printf("%s needs a parameter\n", arg); return ARG_ERROR; } } return ARG_MATCH; } return ARG_NOMATCH; } /* Simple and lean command line argument parsing. */ static int cmp_arg(char **argv, int *pos, const char *long_template, const char *short_template, char **param) { int err; if (long_template) { err = do_cmp_arg(argv, pos, long_template, 0, param); if (err == ARG_MATCH || err == ARG_ERROR) return err; } err = ARG_NOMATCH; if (short_template) err = do_cmp_arg(argv, pos, short_template, 1, param); return err; } static int parse_args(int argc, char *argv[]) { int i, res; char *param; if (argc < 2) goto out_usage; for (i = 1; i < argc; i++) { res = cmp_arg(argv, &i, "--list", "-l", NULL); if (res == ARG_MATCH) { cmdargs.mode = FWCM_LIST; continue; } else if (res == ARG_ERROR) goto out; res = cmp_arg(argv, &i, "--version", "-v", NULL); if (res == ARG_MATCH) { print_banner(); return 1; } else if (res == ARG_ERROR) goto out; res = cmp_arg(argv, &i, "--help", "-h", NULL); if (res == ARG_MATCH) goto out_usage; else if (res == ARG_ERROR) goto out; res = cmp_arg(argv, &i, "--identify", "-i", NULL); if (res == ARG_MATCH) { cmdargs.mode = FWCM_IDENTIFY; continue; } else if (res == ARG_ERROR) goto out; res = cmp_arg(argv, &i, "--unsupported", NULL, NULL); if (res == ARG_MATCH) { cmdargs.unsupported = 1; continue; } else if (res == ARG_ERROR) goto out; res = cmp_arg(argv, &i, "--target-dir", "-w", ¶m); if (res == ARG_MATCH) { cmdargs.target_dir = param; continue; } else if (res == ARG_ERROR) goto out; cmdargs.infile = argv[i]; break; } if (!cmdargs.infile && cmdargs.mode != FWCM_LIST) goto out_usage; return 0; out_usage: print_usage(argc, argv); out: return -1; } int main(int argc, char *argv[]) { FILE *fd; const struct file *file; const struct extract *extract; int err; const char *dir; cmdargs.target_dir = "."; err = parse_args(argc, argv); if (err == 1) return 0; else if (err != 0) return err; if (cmdargs.mode == FWCM_LIST) { print_supported_files(); return 0; } fd = fopen(cmdargs.infile, "rb"); if (!fd) { fprintf(stderr, "Cannot open input file %s\n", cmdargs.infile); return 2; } err = -1; file = find_file(fd); if (!file) goto out_close; if (file->flags & FW_FLAG_V4) dir = V4_FW_DIRNAME; else dir = V3_FW_DIRNAME; extract = file->extract; while (extract->name) { printf("%s %s/%s.fw\n", cmdargs.mode == FWCM_IDENTIFY ? "Contains" : "Extracting", dir, extract->name); extract_or_identify(fd, extract, file->flags); extract++; } err = 0; out_close: fclose(fd); return err; } b43-fwcutter-011/fwcutter.h000064400000000000000000000043351103557476600156430ustar00rootroot00000000000000#ifndef _FWCUTTER_H_ #define _FWCUTTER_H_ #define FW_FLAG_LE 0x01 /* little endian? convert */ #define FW_FLAG_V4 0x02 /* b43 vs. b43legacy */ #define FW_FLAG_UNSUPPORTED 0x04 /* not supported/working */ #define fwcutter_stringify_1(x) #x #define fwcutter_stringify(x) fwcutter_stringify_1(x) #define FWCUTTER_VERSION fwcutter_stringify(FWCUTTER_VERSION_) typedef uint16_t be16_t; /* Big-endian 16bit */ typedef uint32_t be32_t; /* Big-endian 32bit */ #ifdef __DragonFly__ #define bswap_16 bswap16 #define bswap_32 bswap32 #endif #define ARG_MATCH 0 #define ARG_NOMATCH 1 #define ARG_ERROR -1 enum fwcutter_mode { FWCM_EXTRACT = 0, /* default */ FWCM_LIST, FWCM_IDENTIFY, }; struct cmdline_args { const char *infile; const char *target_dir; enum fwcutter_mode mode; int unsupported; }; struct insn { uint32_t opcode; uint16_t op1, op2, op3; }; /* The IV how it's done in the binary driver files. */ struct iv { be16_t reg, size; be32_t val; } __attribute__((__packed__)); enum extract_type { EXT_UNDEFINED, /* error catcher */ EXT_UCODE_1, /* rev <= 4 ucode */ EXT_UCODE_2, /* rev 5..14 ucode */ EXT_UCODE_3, /* rev >= 15 ucode */ EXT_PCM, /* "pcm" values */ EXT_IV, /* initial values */ }; struct extract { const char *name; const uint32_t offset; const uint32_t length; const enum extract_type type; }; #define EXTRACT_LIST_END { .name = NULL, } struct file { const char *name; const char *id; const char *ucode_version; const char *md5; const struct extract *extract; const uint32_t flags; }; /* The header that's put in to every .fw file */ struct fw_header { /* Type of the firmware data */ uint8_t type; /* Version number of the firmware data format */ uint8_t ver; uint8_t __padding[2]; /* Size of the data. For ucode and PCM this is in bytes. * For IV this is in number-of-ivs. */ be32_t size; } __attribute__((__packed__)); #define FW_TYPE_UCODE 'u' #define FW_TYPE_PCM 'p' #define FW_TYPE_IV 'i' #define FW_HDR_VER 0x01 /* The IV in the .fw file */ struct b43_iv { be16_t offset_size; union { be16_t d16; be32_t d32; } data __attribute__((__packed__)); } __attribute__((__packed__)); #define FW_IV_OFFSET_MASK 0x7FFF #define FW_IV_32BIT 0x8000 #endif /* _FWCUTTER_H_ */ b43-fwcutter-011/fwcutter_list.h000064400000000000000000000331531103557476600166760ustar00rootroot00000000000000 /* file member lists */ static struct extract _e08665c5c5b66beb9c3b2dd54aa80cb3[] = { { .name = "ucode2", .offset = 0x59ca0, .length = 0x3fe0, .type = EXT_UCODE_1, }, { .name = "ucode4", .offset = 0x5dc84, .length = 0x4e78, .type = EXT_UCODE_1, }, { .name = "ucode5", .offset = 0x62b00, .length = 0x5700, .type = EXT_UCODE_2, }, { .name = "ucode11", .offset = 0x68204, .length = 0x54a8, .type = EXT_UCODE_2, }, { .name = "pcm4", .offset = 0x6d6b0, .length = 0x520, .type = EXT_PCM, }, { .name = "pcm5", .offset = 0x6dbd4, .length = 0x520, .type = EXT_PCM, }, { .name = "a0g0bsinitvals2", .offset = 0x54ad0 + 0x30d8, .length = 0x18 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals5", .offset = 0x54ad0 + 0x3ae0, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g0initvals5", .offset = 0x54ad0 + 0x3be0, .length = 0x9f0 - 8, .type = EXT_IV, }, { .name = "a0g1bsinitvals5", .offset = 0x54ad0 + 0x50c0, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g0initvals2", .offset = 0x54ad0 + 0x2320, .length = 0xdb8 - 8, .type = EXT_IV, }, { .name = "a0g1initvals5", .offset = 0x54ad0 + 0x45d0, .length = 0x9f0 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals2", .offset = 0x54ad0 + 0x2308, .length = 0x18 - 8, .type = EXT_IV, }, { .name = "b0g0initvals5", .offset = 0x54ad0 + 0x30f0, .length = 0x9f0 - 8, .type = EXT_IV, }, { .name = "b0g0initvals2", .offset = 0x54ad0 + 0x1550, .length = 0xdb8 - 8, .type = EXT_IV, }, { .name = "a0g0bsinitvals5", .offset = 0x54ad0 + 0x4fc0, .length = 0x100 - 8, .type = EXT_IV, }, EXTRACT_LIST_END }; static struct extract _9207bc565c2fc9fa1591f6c7911d3fc0[] = { { .name = "ucode4", .offset = 0x66220 + 0x7ad8, .length = 0x4e68, .type = EXT_UCODE_1, }, { .name = "ucode5", .offset = 0x66220 + 0xc944, .length = 0x5640, .type = EXT_UCODE_2, }, { .name = "ucode11", .offset = 0x66220 + 0x11f90, .length = 0x67e0, .type = EXT_UCODE_2, }, { .name = "ucode13", .offset = 0x66220 + 0x18774, .length = 0x5f60, .type = EXT_UCODE_2, }, { .name = "pcm4", .offset = 0x66220 + 0x1e6d8, .length = 0x520, .type = EXT_PCM, }, { .name = "pcm5", .offset = 0x66220 + 0x1ebfc, .length = 0x520, .type = EXT_PCM, }, { .name = "b0g0initvals4", .offset = 0x66220 + 0x1710, .length = 0xe90 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals4", .offset = 0x66220 + 0x25a0, .length = 0x18 - 8, .type = EXT_IV, }, { .name = "a0g0initvals4", .offset = 0x66220 + 0x25b8, .length = 0xe90 - 8, .type = EXT_IV, }, { .name = "a0g0bsinitvals4", .offset = 0x66220 + 0x3448, .length = 0x18 - 8, .type = EXT_IV, }, { .name = "b0g0initvals5", .offset = 0x66220 + 0x3460, .length = 0xa28 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals5", .offset = 0x66220 + 0x3e88, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g0initvals5", .offset = 0x66220 + 0x3f88, .length = 0xa28 - 8, .type = EXT_IV, }, { .name = "a0g1initvals5", .offset = 0x66220 + 0x49b0, .length = 0xa28 - 8, .type = EXT_IV, }, { .name = "a0g0bsinitvals5", .offset = 0x66220 + 0x53d8, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g1bsinitvals5", .offset = 0x66220 + 0x54d8, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "lp0initvals13", .offset = 0x66220 + 0x5620, .length = 0xb38 - 8, .type = EXT_IV, }, { .name = "lp0bsinitvals13", .offset = 0x66220 + 0x6158, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "b0g0initvals13", .offset = 0x66220 + 0x6258, .length = 0xb40 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals13",.offset = 0x66220 + 0x6d98, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g1initvals13", .offset = 0x66220 + 0x6e98, .length = 0xb40 - 8, .type = EXT_IV, }, { .name = "a0g1bsinitvals13",.offset = 0x66220 + 0x79d8, .length = 0x100 - 8, .type = EXT_IV, }, EXTRACT_LIST_END }; static struct extract _722e2e0d8cc04b8f118bb5afe6829ff9[] = { { .name = "ucode4", .offset = 0x76a10 + 0x8960, .length = 0x4e68, .type = EXT_UCODE_1, }, { .name = "ucode5", .offset = 0x76a10 + 0xd7cc, .length = 0x5640, .type = EXT_UCODE_2, }, { .name = "ucode11", .offset = 0x76a10 + 0x12e18, .length = 0x67e0, .type = EXT_UCODE_2, }, { .name = "ucode13", .offset = 0x76a10 + 0x195fc, .length = 0x5f60, .type = EXT_UCODE_2, }, { .name = "pcm4", .offset = 0x76a10 + 0x1f560, .length = 0x520, .type = EXT_PCM, }, { .name = "pcm5", .offset = 0x76a10 + 0x1fa84, .length = 0x520, .type = EXT_PCM, }, { .name = "b0g0initvals4", .offset = 0x76a10 + 0x1840, .length = 0xe90 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals4", .offset = 0x76a10 + 0x26d0, .length = 0x18 - 8, .type = EXT_IV, }, { .name = "a0g0initvals4", .offset = 0x76a10 + 0x26e8, .length = 0xe90 - 8, .type = EXT_IV, }, { .name = "a0g0bsinitvals4", .offset = 0x76a10 + 0x3578, .length = 0x18 - 8, .type = EXT_IV, }, { .name = "b0g0initvals5", .offset = 0x76a10 + 0x3590, .length = 0xa28 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals5", .offset = 0x76a10 + 0x3fb8, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g0initvals5", .offset = 0x76a10 + 0x40b8, .length = 0xa28 - 8, .type = EXT_IV, }, { .name = "a0g1initvals5", .offset = 0x76a10 + 0x4ae0, .length = 0xa28 - 8, .type = EXT_IV, }, { .name = "a0g0bsinitvals5", .offset = 0x76a10 + 0x5508, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g1bsinitvals5", .offset = 0x76a10 + 0x5608, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "lp0initvals13", .offset = 0x76a10 + 0x64a8, .length = 0xb38 - 8, .type = EXT_IV, }, { .name = "lp0bsinitvals13", .offset = 0x76a10 + 0x6fe0, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "b0g0initvals13", .offset = 0x76a10 + 0x70e0, .length = 0xb40 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals13",.offset = 0x76a10 + 0x7c20, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g1initvals13", .offset = 0x76a10 + 0x7d20, .length = 0xb40 - 8, .type = EXT_IV, }, { .name = "a0g1bsinitvals13",.offset = 0x76a10 + 0x8860, .length = 0x100 - 8, .type = EXT_IV, }, EXTRACT_LIST_END }; static struct extract _1e4763b4cb8cfbaae43e5c6d3d6b2ae7[] = { { .name = "ucode5", .offset = 0x71c80 + 0xacd0, .length = 0x5768, .type = EXT_UCODE_2, }, { .name = "ucode9", .offset = 0x71c80 + 0x1043c, .length = 0x6240, .type = EXT_UCODE_2, }, { .name = "ucode11", .offset = 0x71c80 + 0x16680, .length = 0x74a0, .type = EXT_UCODE_2, }, { .name = "ucode13", .offset = 0x71c80 + 0x1db24, .length = 0x7de0, .type = EXT_UCODE_2, }, { .name = "ucode14", .offset = 0x71c80 + 0x25908, .length = 0x7a90, .type = EXT_UCODE_2, }, { .name = "ucode15", .offset = 0x71c80 + 0x2d39c, .length = 0x7710, .type = EXT_UCODE_3, }, { .name = "pcm5", .offset = 0x71c80 + 0x34ab0, .length = 0x520, .type = EXT_PCM, }, { .name = "b0g0initvals5", .offset = 0x71c80 + 0x14d0, .length = 0xa10 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals5", .offset = 0x71c80 + 0x1ee0, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g0initvals5", .offset = 0x71c80 + 0x1fe0, .length = 0xa10 - 8, .type = EXT_IV, }, { .name = "a0g1initvals5", .offset = 0x71c80 + 0x29f0, .length = 0xa10 - 8, .type = EXT_IV, }, { .name = "a0g0bsinitvals5", .offset = 0x71c80 + 0x3400, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g1bsinitvals5", .offset = 0x71c80 + 0x3500, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "b0g0initvals9", .offset = 0x71c80 + 0x3600, .length = 0xae8 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals9", .offset = 0x71c80 + 0x40e8, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g0initvals9", .offset = 0x71c80 + 0x41e8, .length = 0xae8 - 8, .type = EXT_IV, }, { .name = "a0g1initvals9", .offset = 0x71c80 + 0x4cd0, .length = 0xae8 - 8, .type = EXT_IV, }, { .name = "a0g0bsinitvals9", .offset = 0x71c80 + 0x57b8, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g1bsinitvals9", .offset = 0x71c80 + 0x58b8, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "n0initvals11", .offset = 0x71c80 + 0x59b8, .length = 0xb78 - 8, .type = EXT_IV, }, { .name = "n0bsinitvals11", .offset = 0x71c80 + 0x6530, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "n0absinitvals11", .offset = 0x71c80 + 0x6630, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "lp0initvals13", .offset = 0x71c80 + 0x6730, .length = 0x1360 - 8, .type = EXT_IV, }, { .name = "lp0bsinitvals13", .offset = 0x71c80 + 0x7a90, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "b0g0initvals13", .offset = 0x71c80 + 0x7b90, .length = 0xb60 - 8, .type = EXT_IV, }, { .name = "b0g0bsinitvals13",.offset = 0x71c80 + 0x86f0, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "a0g1initvals13", .offset = 0x71c80 + 0x87f0, .length = 0xb60 - 8, .type = EXT_IV, }, { .name = "a0g1bsinitvals13",.offset = 0x71c80 + 0x9350, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "lp0initvals14", .offset = 0x71c80 + 0x9450, .length = 0xb48 - 8, .type = EXT_IV, }, { .name = "lp0bsinitvals14", .offset = 0x71c80 + 0x9f98, .length = 0x100 - 8, .type = EXT_IV, }, { .name = "lp0initvals15", .offset = 0x71c80 + 0xa098, .length = 0xb38 - 8, .type = EXT_IV, }, { .name = "lp0bsinitvals15", .offset = 0x71c80 + 0xabd0, .length = 0x100 - 8, .type = EXT_IV, }, EXTRACT_LIST_END }; static struct extract _cb8d70972b885b1f8883b943c0261a3c[] = { { .name = "pcm5", .offset = 0x8e554, .type = EXT_PCM, .length = 0x520 }, { .name = "pcm4", .offset = 0x8ea78, .type = EXT_PCM, .length = 0x520 }, { .name = "ucode15", .offset = 0x8ef9c, .type = EXT_UCODE_3, .length = 0x7710 }, { .name = "ucode14", .offset = 0x966b0, .type = EXT_UCODE_2, .length = 0x7a90 }, { .name = "ucode13", .offset = 0x9e144, .type = EXT_UCODE_2, .length = 0x7de0 }, { .name = "ucode11", .offset = 0xa5f28, .type = EXT_UCODE_2, .length = 0x74a0 }, { .name = "ucode9", .offset = 0xad3cc, .type = EXT_UCODE_2, .length = 0x6240 }, { .name = "ucode5", .offset = 0xb3610, .type = EXT_UCODE_2, .length = 0x5768 }, { .name = "ucode4", .offset = 0xb8d7c, .type = EXT_UCODE_1, .length = 0x4ec8 }, { .name = "lp0bsinitvals15", .offset = 0xbdc44, .type = EXT_IV, .length = 0xf8 }, { .name = "lp0initvals15", .offset = 0xbdd44, .type = EXT_IV, .length = 0xb30 }, { .name = "lp0bsinitvals14", .offset = 0xbe87c, .type = EXT_IV, .length = 0xf8 }, { .name = "lp0initvals14", .offset = 0xbe97c, .type = EXT_IV, .length = 0xb40 }, { .name = "a0g1bsinitvals13", .offset = 0xbf4c4, .type = EXT_IV, .length = 0xf8 }, { .name = "a0g1initvals13", .offset = 0xbf5c4, .type = EXT_IV, .length = 0xb58 }, { .name = "b0g0bsinitvals13", .offset = 0xc0124, .type = EXT_IV, .length = 0xf8 }, { .name = "b0g0initvals13", .offset = 0xc0224, .type = EXT_IV, .length = 0xb58 }, { .name = "lp0bsinitvals13", .offset = 0xc0d84, .type = EXT_IV, .length = 0xf8 }, { .name = "lp0initvals13", .offset = 0xc0e84, .type = EXT_IV, .length = 0x1358 }, { .name = "n0absinitvals11", .offset = 0xc21e4, .type = EXT_IV, .length = 0xf8 }, { .name = "n0bsinitvals11", .offset = 0xc22e4, .type = EXT_IV, .length = 0xf8 }, { .name = "n0initvals11", .offset = 0xc23e4, .type = EXT_IV, .length = 0xb70 }, { .name = "a0g1bsinitvals9", .offset = 0xc2f5c, .type = EXT_IV, .length = 0xf8 }, { .name = "a0g0bsinitvals9", .offset = 0xc305c, .type = EXT_IV, .length = 0xf8 }, { .name = "a0g1initvals9", .offset = 0xc315c, .type = EXT_IV, .length = 0xae0 }, { .name = "a0g0initvals9", .offset = 0xc3c44, .type = EXT_IV, .length = 0xae0 }, { .name = "b0g0bsinitvals9", .offset = 0xc472c, .type = EXT_IV, .length = 0xf8 }, { .name = "b0g0initvals9", .offset = 0xc482c, .type = EXT_IV, .length = 0xae0 }, { .name = "a0g1bsinitvals5", .offset = 0xc5314, .type = EXT_IV, .length = 0xf8 }, { .name = "a0g0bsinitvals5", .offset = 0xc5414, .type = EXT_IV, .length = 0xf8 }, { .name = "a0g1initvals5", .offset = 0xc5514, .type = EXT_IV, .length = 0xa08 }, { .name = "a0g0initvals5", .offset = 0xc5f24, .type = EXT_IV, .length = 0xa08 }, { .name = "b0g0bsinitvals5", .offset = 0xc6934, .type = EXT_IV, .length = 0xf8 }, { .name = "b0g0initvals5", .offset = 0xc6a34, .type = EXT_IV, .length = 0xa08 }, { .name = "a0g0bsinitvals4", .offset = 0xc7444, .type = EXT_IV, .length = 0x10 }, { .name = "a0g0initvals4", .offset = 0xc745c, .type = EXT_IV, .length = 0xe88 }, { .name = "b0g0bsinitvals4", .offset = 0xc82ec, .type = EXT_IV, .length = 0x10 }, { .name = "b0g0initvals4", .offset = 0xc8304, .type = EXT_IV, .length = 0xe8c }, EXTRACT_LIST_END }; /* * Links change, so let's not put them into the README. * I still put them here so we know where the file was obtained. */ static const struct file files[] = { { .name = "wl_apsta.o", .id = "FW10", .ucode_version = "295.14", .md5 = "e08665c5c5b66beb9c3b2dd54aa80cb3", .flags = FW_FLAG_LE, .extract = _e08665c5c5b66beb9c3b2dd54aa80cb3, }, { /* http://downloads.openwrt.org/sources/broadcom-wl-4.80.53.0.tar.bz2 */ /* This firmware has the old TX header. */ .name = "wl_apsta.o", .id = "FW11", .ucode_version = "351.126", .md5 = "9207bc565c2fc9fa1591f6c7911d3fc0", .flags = FW_FLAG_LE | FW_FLAG_V4, .extract = _9207bc565c2fc9fa1591f6c7911d3fc0, }, { /* http://downloads.openwrt.org/sources/broadcom-wl-4.80.53.0.tar.bz2 */ /* This firmware has the old TX header. */ .name = "wl_apsta_mimo.o", .id = "FW11", .ucode_version = "351.126", .md5 = "722e2e0d8cc04b8f118bb5afe6829ff9", .flags = FW_FLAG_LE | FW_FLAG_V4, .extract = _722e2e0d8cc04b8f118bb5afe6829ff9, }, { /* ftp://ftp.linksys.com/opensourcecode/wrt150nv11/1.51.3/ */ .name = "wl_ap.o", .id = "FW12", .ucode_version = "410.2160", .md5 = "1e4763b4cb8cfbaae43e5c6d3d6b2ae7", .flags = FW_FLAG_LE | FW_FLAG_V4 | FW_FLAG_UNSUPPORTED, .extract = _1e4763b4cb8cfbaae43e5c6d3d6b2ae7, }, { /* http://mirror2.openwrt.org/sources/broadcom-wl-4.150.10.5.tar.bz2 */ .name = "wl_apsta_mimo.o", .id = "FW13", .ucode_version = "410.2160", .md5 = "cb8d70972b885b1f8883b943c0261a3c", .flags = FW_FLAG_LE | FW_FLAG_V4, .extract = _cb8d70972b885b1f8883b943c0261a3c, }, }; #define FILES (sizeof(files) / sizeof(files[0])) b43-fwcutter-011/md5.c000064400000000000000000000177661103557476600144740ustar00rootroot00000000000000/* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ /* Brutally hacked by John Walker back from ANSI C to K&R (no prototypes) to maintain the tradition that Netfone will compile with Sun's original "cc". */ /* Ripped out ugly K&R again ;) --mbuesch */ /* killed stupid endianness thing --jmberg */ #include /* for memcpy() */ #include "md5.h" /* This function does the Right Thing (tm) on LittleEndian and BigEndian. */ static void byteReverse(unsigned char *buf, unsigned longs) { uint32_t t; do { t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); *(uint32_t *) buf = t; buf += 4; } while (--longs); } /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void MD5Transform(uint32_t *buf, uint32_t *in) { register uint32_t a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void MD5Init(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len) { uint32_t t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { memcpy(p, buf, len); return; } memcpy(p, buf, t); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (uint32_t *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (uint32_t *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memcpy(ctx->in, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void MD5Final(unsigned char *digest, struct MD5Context *ctx) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (uint32_t *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } byteReverse(ctx->in, 14); /* Append length in bits and transform */ ((uint32_t *) ctx->in)[14] = ctx->bits[0]; ((uint32_t *) ctx->in)[15] = ctx->bits[1]; MD5Transform(ctx->buf, (uint32_t *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ } b43-fwcutter-011/md5.h000064400000000000000000000005731103557476600144650ustar00rootroot00000000000000#ifndef FWCUTTER_MD5_H_ #define FWCUTTER_MD5_H_ #include struct MD5Context { uint32_t buf[4]; uint32_t bits[2]; unsigned char in[64]; }; void MD5Init(struct MD5Context *ctx); void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len); void MD5Final(unsigned char *digest, struct MD5Context *ctx); #endif /* FWCUTTER_MD5_H_ */