int hex2bin(unsigned char *ib, unsigned char *ob) /* convert a \0 terminated string of hex digits into the binary repr. and returns the number of bytes created. ib and ob may be the same buffer ! */ { int i=0; unsigned char val = 0; #define HEX2BIN(x) \ ((x) <= '9' ? (x)-'0' :\ (x) >= 'a' && (x) <= 'f' ? (x)-'a'+10 : (x)-'A'-10) while (*ib) { if (i%2) *ob++ = (val<<4) | HEX2BIN(*ib); else val = HEX2BIN(*ib); i++; ib++; } if (i%2) { /* we got an odd number of hexdigits - quietly assume a trailing 0 */ *ob = val<<4; i++; } return i/2; }
int hex2bin(char *str, char **hex) { char *ptr; int i, l = strlen(str); if (l & 1) return 0; *hex = malloc(l / 2); ptr = *hex; if (!ptr) return 0; for (i = 0; i < l; i += 2) *ptr++ = (HEX2BIN(str[i]) << 4) | HEX2BIN(str[i+1]); return l / 2; }
// Read a hexadecimal string from the user to use as the initial seed in the // key generation routine. If the hex-string is less than 72 bytes, then the // input key will be extended to fill the full key length. If the length is // greater than 72 bytes, then the key will be compacted by XORing the remaining // bytes with the existing bytes in a round-robin approach. int get_input() { int idx; bool ok = false; while (!ok) { printf("Enter seed-key in hexadecimal (Ex: 573BE15A): "); // Read line from stdin char* line = NULL; size_t len = 0; if (getline(&line, &len, stdin) == -1) PRINT_RETURN("Could not read line\n", -1); strtok(line, "\r\n"); // Verify that the key is okay int clen = strlen(line); ok = (clen > 0); for (idx = 0; idx < clen; idx++) ok = (ok && isxdigit(line[idx])); // Parse the key (handles key extending and compacting) int klen = sizeof(arr_key); memset(arr_key, '\0', klen); uint8_t* _arr_key = (uint8_t*)arr_key; if (ok) { for (idx = 0; idx < MAX(clen, klen*2); idx++) { int shift = (idx%2) ? 0 : 4; _arr_key[(idx/2) % klen] ^= HEX2BIN(line[idx % clen]) << shift; } } free(line); } return 0; }
/** * return 4-bit checksum of product * * product[] : 12-byte string * */ uint32_t chksum(char product[]) { uint32_t sum = 16; int i; for (i = 0; i < PRODUCT_NBR_LEN - 1; i++) { sum += HEX2BIN(product[i]); sum = (sum >= 17) ? (sum - 16) : sum; sum <<= 1; sum = (sum >= 17) ? (sum - 17) : sum; } sum = (17 - sum); return (sum != 16) ? sum : 0; }
int RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, int age) { FILE *f = NULL; char *path, date[64], cctim[64]; long pos = 0; time_t ctim = -1, cnow; int i, got = 0, ret = 0; unsigned int hlen; struct info in = {0}; struct HTTP_ctx http = {0}; HTTPResult httpres; z_stream zs = {0}; AVal home, hpre; date[0] = '\0'; #ifdef _WIN32 #ifdef XBMC4XBOX hpre.av_val = "Q:"; hpre.av_len = 2; home.av_val = "\\UserData"; #else hpre.av_val = getenv("HOMEDRIVE"); hpre.av_len = strlen(hpre.av_val); home.av_val = getenv("HOMEPATH"); #endif #define DIRSEP "\\" #else /* !_WIN32 */ hpre.av_val = ""; hpre.av_len = 0; home.av_val = getenv("HOME"); #define DIRSEP "/" #endif if (!home.av_val) home.av_val = "."; home.av_len = strlen(home.av_val); /* SWF hash info is cached in a fixed-format file. * url: <url of SWF file> * ctim: HTTP datestamp of when we last checked it. * date: HTTP datestamp of the SWF's last modification. * size: SWF size in hex * hash: SWF hash in hex * * These fields must be present in this order. All fields * besides URL are fixed size. */ path = malloc(hpre.av_len + home.av_len + sizeof(DIRSEP ".swfinfo")); sprintf(path, "%s%s" DIRSEP ".swfinfo", hpre.av_val, home.av_val); f = fopen(path, "r+"); while (f) { char buf[4096], *file, *p; file = strchr(url, '/'); if (!file) break; file += 2; file = strchr(file, '/'); if (!file) break; file++; hlen = file - url; p = strrchr(file, '/'); if (p) file = p; else file--; while (fgets(buf, sizeof(buf), f)) { char *r1; got = 0; if (strncmp(buf, "url: ", 5)) continue; if (strncmp(buf + 5, url, hlen)) continue; r1 = strrchr(buf, '/'); i = strlen(r1); r1[--i] = '\0'; if (strncmp(r1, file, i)) continue; pos = ftell(f); while (got < 4 && fgets(buf, sizeof(buf), f)) { if (!strncmp(buf, "size: ", 6)) { *size = strtol(buf + 6, NULL, 16); got++; } else if (!strncmp(buf, "hash: ", 6)) { unsigned char *ptr = hash, *in = (unsigned char *) buf + 6; int l = strlen((char *) in) - 1; for (i = 0; i < l; i += 2) *ptr++ = (HEX2BIN(in[i]) << 4) | HEX2BIN(in[i + 1]); got++; } else if (!strncmp(buf, "date: ", 6)) { buf[strlen(buf) - 1] = '\0'; strncpy(date, buf + 6, sizeof(date)); got++; } else if (!strncmp(buf, "ctim: ", 6)) { buf[strlen(buf) - 1] = '\0'; ctim = make_unix_time(buf + 6); got++; } else if (!strncmp(buf, "url: ", 5)) break; } break; } break; } cnow = time(NULL); /* If we got a cache time, see if it's young enough to use directly */ if (age && ctim > 0) { ctim = cnow - ctim; ctim /= 3600 * 24; /* seconds to days */ if (ctim < age) /* ok, it's new enough */ goto out; } in.first = 1; HMAC_setup(in.ctx, "Genuine Adobe Flash Player 001", 30); inflateInit(&zs); in.zs = &zs; http.date = date; http.data = ∈ httpres = HTTP_get(&http, url, swfcrunch); inflateEnd(&zs); if (httpres != HTTPRES_OK && httpres != HTTPRES_OK_NOT_MODIFIED) { ret = -1; if (httpres == HTTPRES_LOST_CONNECTION) RTMP_Log(RTMP_LOGERROR, "%s: connection lost while downloading swfurl %s", __FUNCTION__, url); else if (httpres == HTTPRES_NOT_FOUND) RTMP_Log(RTMP_LOGERROR, "%s: swfurl %s not found", __FUNCTION__, url); else RTMP_Log(RTMP_LOGERROR, "%s: couldn't contact swfurl %s (HTTP error %d)", __FUNCTION__, url, http.status); } else { if (got && pos) fseek(f, pos, SEEK_SET); else { char *q; if (!f) f = fopen(path, "w"); if (!f) { int err = errno; RTMP_Log(RTMP_LOGERROR, "%s: couldn't open %s for writing, errno %d (%s)", __FUNCTION__, path, err, strerror(err)); ret = -1; goto out; } fseek(f, 0, SEEK_END); q = strchr(url, '?'); if (q) i = q - url; else i = strlen(url); fprintf(f, "url: %.*s\n", i, url); } strtime(&cnow, cctim); fprintf(f, "ctim: %s\n", cctim); if (!in.first) { HMAC_finish(in.ctx, hash, hlen); *size = in.size; fprintf(f, "date: %s\n", date); fprintf(f, "size: %08x\n", in.size); fprintf(f, "hash: "); for (i = 0; i < SHA256_DIGEST_LENGTH; i++) fprintf(f, "%02x", hash[i]); fprintf(f, "\n"); } } HMAC_close(in.ctx); out: free(path); if (f) fclose(f); return ret; }