Not tried it, to be honest, here's the source in C:
/*
pakgen.c by VAXbusters International
purdy code is:
(C) Copyright 1991-1994 The Trustees of Indiana University
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <limits.h>
#define MAX_U32 4294967295UL
#define MAX_32 2147483647L
#if (ULONG_MAX == MAX_U32)
typedef unsigned long ui32_t;
#endif
#if ((UINT_MAX == MAX_U32) && \
(ULONG_MAX != MAX_U32))
typedef unsigned int ui32_t;
#endif
#if ((USHRT_MAX == MAX_U32) && \
(UINT_MAX != MAX_U32) && \
(ULONG_MAX != MAX_U32))
typedef unsigned short ui32_t;
#endif
#if (LONG_MAX == MAX_32)
typedef long i32_t;
#endif
#if ((INT_MAX == MAX_32) && \
(LONG_MAX != MAX_32))
typedef int i32_t;
#endif
#if ((SHRT_MAX == MAX_32) && \
(INT_MAX != MAX_32) && \
(LONG_MAX != MAX_32))
typedef short i32_t;
#endif
/* 200, 2a0, 250, 278, 228, 2c8, 2f0, 318, 340, 368 */
struct s {
i32_t l[5][2];
} ctable[] = {
{
{
{ -587, -1 },
{ -29, -1 },
{ -139, -1 },
{ -947, -1 },
{ -257, -1 },
}
},
{
{
{ -53, -1 },
{ -127, -1 },
{ -257, -1 },
{ -337, -1 },
{ -419, -1 },
}
},
{
{
{ -521, -1 },
{ -229, -1 },
{ -379, -1 },
{ -53, -1 },
{ -907, -1 },
}
},
{
{
{ -43, -1 },
{ -467, -1 },
{ -613, -1 },
{ -761, -1 },
{ -967, -1 },
}
},
{
{
{ -821, -1 },
{ -487, -1 },
{ -107, -1 },
{ -71, -1 },
{ -643, -1 },
}
},
{
{
{ -13, -1 },
{ -839, -1 },
{ -431, -1 },
{ -563, -1 },
{ -181, -1 },
}
},
{
{
{ -83, -1 },
{ -283, -1 },
{ -863, -1 },
{ -349, -1 },
{ -127, -1 },
}
},
{ {
{ -739, -1 },
{ -313, -1 },
{ -97, -1 },
{ -683, -1 },
{ -157, -1 },
}
},
{ {
{ -61, -1 },
{ -199, -1 },
{ -787, -1 },
{ -401, -1 },
{ -653, -1 },
}
},
{
{
{ -991, -1 },
{ -601, -1 },
{ -19, -1 },
{ -449, -1 },
{ -743, -1 },
}
},
};
#define PRODUCT_NAME_TYPE 2
#define ISSUER_TYPE 4
#define AUTHORIZATION_TYPE 6
#define PRODUCER_TYPE 1
#define UNITS_TYPE 7
#define AVAILABILITY_TYPE 8
#define ACTIVITY_TYPE 9
#define KEY_OPTIONS_TYPE 17
ui32_t crctable[16] = {
0x00000000,
0x1DB71064,
0x3B6E20C8,
0x26D930AC,
0x76DC4190,
0x6B6B51F4,
0x4DB26158,
0x5005713C,
0xEDB88320,
0xF00F9344,
0xD6D6A3E8,
0xCB61B38C,
0x9B64C2B0,
0x86D3D2D4,
0xA00AE278,
0xBDBDF21C,
};
ui32_t lib_crc(int len,
unsigned char *array,
ui32_t initcrc,
ui32_t *crctbl) {
ui32_t res = initcrc;
while (len--) {
ui32_t c = *(array++);
res = res ^ c;
res = (res >> 4) ^ crctbl[res & 15];
res = (res >> 4) ^ crctbl[res & 15];
}
return res;
}
static void pqexp(i32_t num[],i32_t power);
static void pqmod(i32_t nump[]);
static void pqmul(i32_t mulr[], i32_t muld[], i32_t prod[]);
static void emulq(i32_t mulr, i32_t muld, i32_t prod[]);
static void pqlsh(i32_t num[]);
static void pqadd(i32_t add[], i32_t sum[]);
void lib_emul(i32_t *mulr, i32_t *muld, i32_t *addend, i32_t prod[]) {
long long res = (long long)*mulr * (long long)*muld + (long long)*addend;
prod[0] = (i32_t)(res & 0xFFFFFFFF);
prod[1] = (i32_t)((res >> 32ll) & 0xFFFFFFFFll);
}
void lib_addx(ui32_t *a1, ui32_t *a2, ui32_t *dst) {
unsigned long long a1_0 = a1[0],
a1_1 = a1[1],
a2_0 = a2[0],
a2_1 = a2[1];
unsigned long long ll1 = a1_0 + (a1_1 << 32);
unsigned long long ll2 = a2_0 + (a2_1 << 32);
unsigned long long res = ll1 + ll2;
dst[0] = (res & 0xFFFFFFFF);
dst[1] = (res >> 32) & 0xFFFFFFFF;
}
#define CRC_DISPATCH(num, array) \
{ (num)[0] = ((array)[1] << 24) | ((array)[0] << 8); \
(num)[1] = (array)[2] | ((array)[3] << 16); }
#define COPY_32BIT_TO_ARRAY(val, array) \
{ (array)[0] = (val) & 0xFF; \
(array)[1] = ((val) >> 8) & 0xFF; \
(array)[2] = ((val) >> 16) & 0xFF; \
(array)[3] = ((val) >> 24) & 0xFF; }
#define COPY_STRING_TO_BUFFER(str, type, buf) \
{ len = strlen((str)); \
memcpy(buf, (str), len); \
(buf)[len++] = (type); \
(buf)[len++] = 0; }
void calc_checksum(char *product_name,
char *issuer,
char *authorization,
char *producer,
char *units,
char *availability,
char *activity,
unsigned char *key_options,
int salt,
ui32_t *cksum) {
unsigned char tmp[256];
int len;
ui32_t crcnum[2];
ui32_t crcval;
ui32_t inicrc = 0xFFFFFFFF;
unsigned char crc_array[4];
cksum[0] = 0;
cksum[1] = 0;
if (product_name != NULL) {
/* PRODUCT NAME */
COPY_STRING_TO_BUFFER(product_name, PRODUCT_NAME_TYPE, tmp);
crcval = lib_crc(len, tmp, inicrc, crctable);
COPY_32BIT_TO_ARRAY(crcval, crc_array);
CRC_DISPATCH(crcnum, crc_array);
lib_addx(crcnum, cksum, cksum);
}
if ((key_options[0] != 0) ||
(key_options[1] != 0)) {
/* OPTIONS */
memcpy(tmp, key_options, 8);
tmp[8] = KEY_OPTIONS_TYPE;
tmp[9] = 0;
crcval = lib_crc(10, tmp, inicrc, crctable);
COPY_32BIT_TO_ARRAY(crcval, crc_array);
CRC_DISPATCH(crcnum, crc_array);
lib_addx(crcnum, cksum, cksum);
}
if (issuer != NULL) {
/* ISSUER */
COPY_STRING_TO_BUFFER(issuer, ISSUER_TYPE, tmp);
crcval = lib_crc(len, tmp, inicrc, crctable);
COPY_32BIT_TO_ARRAY(crcval, crc_array);
CRC_DISPATCH(crcnum, crc_array);
lib_addx(crcnum, cksum, cksum);
}
if (authorization != NULL) {
/* AUTHORIZATION */
COPY_STRING_TO_BUFFER(authorization, AUTHORIZATION_TYPE, tmp);
crcval = lib_crc(len, tmp, inicrc, crctable);
COPY_32BIT_TO_ARRAY(crcval, crc_array);
CRC_DISPATCH(crcnum, crc_array);
lib_addx(crcnum, cksum, cksum);
}
if (units != NULL) {
/* UNITS */
COPY_STRING_TO_BUFFER(units, UNITS_TYPE, tmp);
crcval = lib_crc(len, tmp, inicrc, crctable);
COPY_32BIT_TO_ARRAY(crcval, crc_array);
CRC_DISPATCH(crcnum, crc_array);
lib_addx(crcnum, cksum, cksum);
}
if (producer != NULL) {
/* UNITS */
COPY_STRING_TO_BUFFER(producer, PRODUCER_TYPE, tmp);
crcval = lib_crc(len, tmp, inicrc, crctable);
COPY_32BIT_TO_ARRAY(crcval, crc_array);
CRC_DISPATCH(crcnum, crc_array);
lib_addx(crcnum, cksum, cksum);
}
if (availability != NULL) {
/* AVAILABILITY */
COPY_STRING_TO_BUFFER(availability, AVAILABILITY_TYPE, tmp);
crcval = lib_crc(len, tmp, inicrc, crctable);
COPY_32BIT_TO_ARRAY(crcval, crc_array);
CRC_DISPATCH(crcnum, crc_array);
lib_addx(crcnum, cksum, cksum);
}
if (activity != NULL) {
/* ACTIVITY */
COPY_STRING_TO_BUFFER(activity, ACTIVITY_TYPE, tmp);
crcval = lib_crc(len, tmp, inicrc, crctable);
COPY_32BIT_TO_ARRAY(crcval, crc_array);
CRC_DISPATCH(crcnum, crc_array);
lib_addx(crcnum, cksum, cksum);
}
}
void format_pwd(ui32_t pwd[], int salt) {
char chars[17] = "ABCDEFGHIJKLMNOP";
int i, j, k;
printf("%d-", salt);
for (k = 0; k < 2; k++) {
i32_t tmp = pwd[k];
for (j = 0; j < 2; j++) {
for (i = 0; i < 4; i++) {
printf("%c", chars[(tmp >> 28) & 0xF]);
tmp <<= 4;
}
if (j != 1)
printf("-");
}
if (k != 1)
printf("-");
}
printf("\n");
}
#define quadasgn(d,l,h) (d[0] = l,d[1] = h)
#define quadcopy(s,d) (d[0] = s[0],d[1] = s[1])
static i32_t a = 59, n0 = (1 << 24) - 3,n1 = (1 << 24) - 63;
static void purdy(ui32_t epwd[], struct s *sc)
{
int i = 0;
i32_t power,rs1[2],rs2[2],rs3[2];
i32_t c[5][2];
memcpy(c, sc->l, sizeof(c));
pqmod((i32_t *)epwd);
/*
* Get x^n1.
*/
quadcopy(epwd,rs2);
power = n1;
pqexp(rs2,power);
/*
* Get x^(n0 - n1) + c1. Obtain x^n0 + x^n1 * c1 by multiplying the
* first two number.
*/
quadcopy(epwd,rs1);
power = n0 - n1;
pqexp(rs1,power);
pqadd(c[i],rs1);
pqmul(rs2,rs1,rs1);
i++;
/*
* Get x * c2 + c3. Obtaining x^2 * c2 + x * c3 by multiplying x to
* the result.
*/
quadcopy(epwd,rs2);
pqmul(c[i],rs2,rs2);
i++;
pqadd(c[i],rs2);
i++;
quadcopy(epwd,rs3);
pqmul(rs3,rs2,rs2);
/*
* Get x^2 * c2 + x * c3 + c4. Obtaining x^3 * c2 + x^2 * c3 + x * c4
* by multiply x to the last result.
*/
pqadd(c[i],rs2);
i++;
quadcopy(epwd,rs3);
pqmul(rs3,rs2,rs2);
/*
* Add c5 and the first number to produce the result.
*/
pqadd(c[i],rs2);
pqadd(rs2,rs1);
quadcopy(rs1,epwd);
}
/*
* pqexp() replaces the quadword num with num^p where p is of the
* form p = 2^64 - a.
* Parameters:
* 1) long num[2] Quadword to be raised to the given power
* 2) long power Raised to this power
* Return values:
* None
*/
static void pqexp(i32_t num[],i32_t power)
{
i32_t multi[2],save_num[2];
if (power <= 0) return;
quadasgn(multi,1,0);
quadcopy(num,save_num);
for ( ; ; ) {
if (power & 0x00000001) {
pqmul(num,multi,num);
quadcopy(num,multi);
if ((power & 0xfffffffe) == 0) break;
}
pqmul(save_num,save_num,num);
quadcopy(num,save_num);
power >>= 1;
}
}
/*
* pqmod() replaces the quadword num with num mod p where p is of the
* form p = 2^64 - a.
* Parameters:
* 1) long num[2] Quadword to be mod by p
* Return values:
* None
*/
static void pqmod(i32_t num[])
{
if ((ui32_t)num[0] < (ui32_t)-a) return;
if ((ui32_t)num[1] < (ui32_t)-1) return;
num[0] += a;
num[1] += 1;
}
/*
* pqmul() computes the product mulr * muld mod p where p is of the
* form p = 2^64 - a.
* The product may be form as the sum of four longword multiplications
* which are scaled by powers of 2^32 by evaluating:
* 2^64 * v * z + 2^32 * (v * y + u * z) + u * y
* where u = muld[0]
* v = muld[1]
* y = mulr[0]
* z = mulr[1]
* Parameters:
* 1) long mulr[2] Quadword multiplier
* 2) long muld[2] Quadword multiplicand
* 3) long prod[2] Quadword product
* Return values:
* None
*/
static void pqmul(i32_t mulr[], i32_t muld[], i32_t prod[])
{
i32_t tmp[2],rs1[2],rs2[2];
/*
* Get 2^32 * v * z.
*/
emulq(mulr[1],muld[1],tmp);
pqmod(tmp);
pqlsh(tmp);
quadcopy(tmp,rs2);
/*
* Get v * y and add in the above sum.
*/
emulq(mulr[0],muld[1],tmp);
pqmod(tmp);
quadcopy(tmp,rs1);
/*
* Get u * z and add in the above sum. Obtain the first two
* items by pqlsh() the sum.
*/
emulq(mulr[1],muld[0],tmp);
pqmod(tmp);
pqadd(tmp,rs1);
pqadd(rs2,rs1);
pqlsh(rs1);
/*
* Get u * y and add in the above sum.
*/
emulq(mulr[0],muld[0],tmp);
pqmod(tmp);
pqadd(tmp,rs1);
quadcopy(rs1,prod);
}
/*
* emulq() knows how to multiply two ui32_twords, producing an
* unsigned quadword product.
* Parameters:
* 1) long mulr Longword multiplier
* 2) long muld Longword multiplicand
* 3) long prod[2] Quadword product
* Return values:
* None
*/
static void emulq(i32_t mulr, i32_t muld, i32_t prod[])
{
i32_t compensate = 0;
i32_t null = 0;
lib_emul(&mulr,&muld,&null,prod);
if (mulr < 0) compensate += muld;
if (muld < 0) compensate += mulr;
prod[1] += compensate;
}
/*
* pqlsh() computes the product 2^32 * u mod p where p is of the
* form p = 2^64 - a.
* Parameters:
* 1) long num[2] Quadword to be mod by p
* Return values:
* None
*/
#define ASH 32
static void pqlsh(i32_t num[])
{
i32_t tmp[2],mask = 0x80000000;
emulq(num[1],a,tmp);
/* num[1] <<= ASH; */
num[1] = 0;
num[1] |= (ui32_t)((mask >>= ASH - 1) & num[0]) >> (32 -
ASH);
/* num[0] <<= ASH; */
num[0] = 0;
pqadd(tmp,num);
}
/*
* pqadd() computes the sum add + sum mod p where p is of the
* form p = 2^64 - a.
* Parameters:
* 1) long add[2] Quadword addend
* 2) long sum[2] Quadword sum
* Return values:
* None
*/
static void pqadd(i32_t add[], i32_t sum[])
{
int c0,c1;
if ((ui32_t)sum[0] > (ui32_t)-1 - (ui32_t)add[0])
c0 = 1;
else
c0 = 0;
sum[0] += add[0];
if ((ui32_t)(sum[1] + c0) > (ui32_t)-1 - (ui32_t)add[1])
c1 = 1;
else
c1 = 0;
sum[1] += add[1] + c0;
if (!c1 && (ui32_t)sum[1] < (ui32_t)-1)
return;
if ((ui32_t)sum[0] > (ui32_t)-1 - (ui32_t)a)
c0 = 1;
else
c0 = 0;
sum[0] += a;
sum[1] += c0;
}
static void strtoupper(char *str) {
while (*str) {
*str = toupper(*str);
str++;
}
}
static void usage(void) {
fprintf(stderr,
"Usage: pakgen [-s salt] [-p producer] [-i issuer] [-a authorization]\n");
fprintf(stderr,
"\t[-u units] [-v availability] [-c activity] ");
fprintf(stderr,
"[-A] [-M] [-R] [-N] [-t]\n\n");
fprintf(stderr, "\t-A : key option ALPHA\n");
fprintf(stderr, "\t-N : key option NO_SHARE\n");
fprintf(stderr, "\t-R : key option RESERVE_UNITS\n");
fprintf(stderr, "\t-M : key option MOD_UNITS\n\n");
fprintf(stderr, "\t-t : output lmf file, pipe into lmf with \"lmf
-\"\n");
fprintf(stderr, "\t-s : purdy salt (0 - 9)\n");
}
int main(int argc, char *argv[]) {
unsigned char options[8] = {
0, 0, 0, 0,
0, 0, 0, 0
};
ui32_t epwd[2];
int salt = 2;
int c;
char *product_name = NULL;
char *issuer = NULL;
char *authorization = NULL;
char *producer = NULL;
char *units = NULL;
char *availability = NULL;
char *activity = NULL;
int tru64 = 0;
while ((c = getopt(argc, argv, "hi:a:p:u:c:v:AMRNts:")) >= 0) {
switch (c) {
case 'h':
usage();
exit(EXIT_SUCCESS);
break;
case 's':
salt = atoi(optarg);
if ((salt < 0) || (salt > 9)) {
usage();
exit(EXIT_FAILURE);
}
break;
case 't':
tru64 = 1;
break;
case 'A':
options[1] |= 0x2;
break;
case 'M':
options[0] |= 0x4;
break;
case 'R':
options[0] |= 0x80;
break;
case 'N':
options[0] |= 0x8;
break;
case 'i':
if (issuer)
free(issuer);
issuer = strdup(optarg);
strtoupper(issuer);
break;
case 'a':
if (authorization)
free(authorization);
authorization = strdup(optarg);
strtoupper(authorization);
break;
case 'p':
if (producer)
free(producer);
producer = strdup(optarg);
strtoupper(producer);
break;
case 'u':
if (units)
free(units);
units = strdup(optarg);
break;
case 'v':
if (availability)
free(availability);
availability = strdup(optarg);
strtoupper(availability);
break;
case 'c':
if (activity)
free(activity);
activity = strdup(optarg);
strtoupper(activity);
break;
}
}
if (optind != (argc - 1)) {
usage();
exit(EXIT_FAILURE);
}
product_name = argv[optind];
strtoupper(product_name);
if (product_name == NULL) {
usage();
exit(EXIT_FAILURE);
}
/*
product name,
issuer,
authorization,
producer,
units,
availability,
activity,
key_options
*/
calc_checksum(product_name,
issuer,
authorization,
producer,
units,
availability,
activity,
options,
salt, epwd);
purdy(epwd, ctable + salt);
if (!tru64) {
printf("LICENSE REGISTER %s -\n", product_name);
if (issuer != NULL)
printf(" /ISSUER=%s -\n", issuer);
if (authorization != NULL)
printf(" /AUTHORIZATION=%s -\n", authorization);
if (producer != NULL)
printf(" /PRODUCER=%s -\n", producer);
if (units != NULL)
printf(" /UNITS=%s -\n", units);
if (availability != NULL)
printf(" /AVAILABILITY=%s -\n", availability);
if (activity != NULL)
printf(" /ACTIVITY=%s -\n", activity);
if ((options[0] != 0) ||
(options[1] != 0)) {
int cnt = 0;
printf(" /OPTIONS=(");
if (options[0] & 0x4) {
cnt = 1;
printf("MOD_UNITS");
}
if (options[0] & 0x8) {
if (cnt)
printf(",");
else
cnt = 1;
printf("NO_SHARE");
}
if (options[0] & 0x80) {
if (cnt)
printf(",");
else
cnt = 1;
printf("RESERVE_UNITS");
}
if (options[1] & 0x2) {
if (cnt)
printf(",");
else
cnt = 1;
printf("ALPHA");
}
printf(") -\n");
}
printf(" /CHECKSUM=");
format_pwd(epwd, salt);
} else {
printf("%30s: %s\n", "Issuer", (issuer ? issuer : ""));
printf("%30s: %s\n", "Authorization Number",
(authorization ? authorization : ""));
printf("\n");
printf("%30s: %s\n", "Product Name",
(product_name ? product_name : ""));
printf("%30s: %s\n", "Producer", (producer ? producer :
""));
printf("\n");
printf("%30s: %s\n", "Number of units", (units ? units :
""));
printf("%30s: \n", "Version");
printf("%30s: \n", "Product Release Date");
printf("\n");
printf("%30s: \n", "Key Termination Date");
printf("\n");
printf("%30s: %s\n", "Availability Table Code",
(availability ? availability : ""));
printf("%30s: %s\n", "Activity Table Code",
(activity ? activity : ""));
printf("\n");
printf("%30s: ", "Key Options");
if ((options[0] != 0) ||
(options[1] != 0)) {
int cnt = 0;
if (options[0] & 0x4) {
cnt = 1;
printf("MOD_UNITS");
}
if (options[0] & 0x8) {
if (cnt)
printf(",");
else
cnt = 1;
printf("NO_SHARE");
}
if (options[0] & 0x80) {
if (cnt)
printf(",");
else
cnt = 1;
printf("RESERVE_UNITS");
}
if (options[1] & 0x2) {
if (cnt)
printf(",");
else
cnt = 1;
printf("ALPHA");
}
}
printf("\n");
printf("%30s: \n", "Product Token");
printf("%30s: \n", "Hardware-Id");
printf("%30s: ", "Checksum");
format_pwd(epwd, salt);
}
return 1;
}
On 17 Sep 2009, at 23:46, Zane H. Healy wrote:
Does it work for Itanium?
Zane
On Thu, 17 Sep 2009, Sampsa Laine wrote:
I copied them all, can not be bothered distinguishing between the ones licensed for
hobbyist use and not.
I happen to have a PAK generator that works, if one wanted to play around with a package
or two...
Sampsa
On 17 Sep 2009, at 23:12, Zane H. Healy wrote:
Are you doing it as individual software packages? That is how it would be
the most bandwidth friendly. Also only copy the software packages supported
by the Hobbyist Licenses. What SPL's?
Zane
On Thu, 17 Sep 2009, Sampsa Laine wrote:
I've just loaded the Alpha SPL I have here came on 9 CDs, I've loaded these onto
RHESUS.
Sampsa
On 17 Sep 2009, at 22:53, Dennis Boone wrote:
I thought it might be useful to set up a library of VMS media kits (and
maybe RSX / RSTS etc as well) - basically images of VMS install CDs,
layered products etc, all in one convenient location.
Seems like a great idea. Looks like VAX SPL CDs run 2-3 GB gzipped,
closer to 6 GB uncompressed. One Alpha SPL looks to be about 4 GB
compressed.
De