+++ /dev/null
-/*
- * monosn.c: Mono String Name Utility
- *
- * Author:
- * Paolo Molaro (lupus@ximian.com)
- *
- * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- *
- */
-#include <mono/metadata/class.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/tokentype.h>
-#include <mono/metadata/appdomain.h>
-#include <mono/metadata/assembly.h>
-#include "mono/utils/mono-digest.h"
-/* trim headers */
-
-#include <string.h>
-#include <ctype.h>
-
-#define RSA1_MAGIC 0x32415351
-#define RSA2_MAGIC 0x32415352
-#define PRIVKEY_MAGIC 0x00000207
-#define PUBKEY_MAGIC 0x00008004
-
-typedef struct {
- guchar type, version;
- guint16 reserved1;
- guint32 algid;
-} MonoKeyHeader;
-
-typedef struct {
- MonoKeyHeader header;
- guint32 bitlen;
- guint32 exponent;
- guchar modulus [MONO_ZERO_LEN_ARRAY];
-} MonoRSAPubHeader;
-
-static void
-print_data (const char *data, int len)
-{
- int i;
- for (i = 0; i < len; ++i) {
- if (i && !(i % 32))
- printf ("\n");
- printf ("%02x", data [i] & 0xff);
- }
- printf ("\n");
-}
-
-static int
-show_token (const char *file, int is_assembly, int show_pubkey) {
- char token [20];
- if (!is_assembly) {
- char *pubkey;
- gsize len;
- if (!g_file_get_contents (file, &pubkey, &len, NULL)) {
- printf ("Cannot load file: %s\n", file);
- return 2;
- }
- mono_digest_get_public_token (token, pubkey, len);
- if (show_pubkey) {
- printf ("Public key is\n");
- print_data (pubkey, len);
- }
- g_free (pubkey);
- } else {
- MonoImage *image;
- const char *pubkey;
- guint32 len;
-
- mono_metadata_init ();
- mono_images_init ();
- mono_assemblies_init ();
- mono_loader_init ();
-
- image = mono_image_open (file, NULL);
- if (!image) {
- printf ("Cannot open image file: %s\n", file);
- return 2;
- }
- pubkey = mono_image_get_public_key (image, &len);
- if (!pubkey) {
- printf ("%s does not represent a strongly named assembly\n", mono_image_get_name(image));
- mono_image_close (image);
- return 2;
- }
- if (show_pubkey) {
- printf ("Public key is\n");
- print_data (pubkey, len);
- }
- mono_digest_get_public_token (token, pubkey, len);
- mono_image_close (image);
- }
- printf ("Public key token is ");
- print_data (token, 8);
- return 0;
-}
-
-static int
-extract_data_to_file (int pubk, const char *assembly, const char *outfile) {
- MonoImage *image;
- FILE *file;
- const char *pubkey;
- guint32 len;
-
- image = mono_image_open (assembly, NULL);
- if (!image) {
- printf ("Cannot open image file: %s\n", assembly);
- return 2;
- }
- if (pubk)
- pubkey = mono_image_get_public_key (image, &len);
- else
- pubkey = mono_image_get_strong_name (image, &len);
- if (!pubkey) {
- printf ("%s does not represent a strongly named assembly\n", mono_image_get_name(image));
- mono_image_close (image);
- return 2;
- }
- if (!(file = fopen (outfile, "wb"))) {
- printf ("Cannot open output file: %s\n", outfile);
- return 2;
- }
- fwrite (pubkey, len, 1, file);
- fclose (file);
- mono_image_close (image);
- return 0;
-}
-
-const static guint8 asciitable [128] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
- 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
- 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
- 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
- 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
- 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
- 0xff, 0xff
-};
-
-/* data is changed in place */
-static char*
-pem_decode (guchar *data, int len, int *rlen) {
- guchar *p, *s;
- int b64len, i, rem = 0, full;
- int b0, b1, b2, b3, offset, dlen;
-
- p = strstr (data, "-----BEGIN");
- s = strstr (data, "\n-----END");
- if (!p || !s)
- return NULL;
- while (*p != '\n') p++;
- *s = 0;
- s = data = p;
- while (*p) {
- if (isalnum (*p) || *p == '+' || *p == '=' || *p == '/') {
- *s++ = *p++;
- } else {
- p++;
- }
- }
- *s = 0;
- b64len = s - data;
-
- full = b64len >> 2;
- if (data [b64len - 1] == '=') {
- full--;
- rem++;
- }
- if (data [b64len - 2] == '=')
- rem++;
- offset = 0;
- p = data;
- for (i = 0; i < full; ++i) {
- b0 = asciitable [data [offset++]];
- b1 = asciitable [data [offset++]];
- b2 = asciitable [data [offset++]];
- b3 = asciitable [data [offset++]];
-
- *p++ = (b0 << 2) | (b1 >> 4);
- *p++ = (b1 << 4) | (b2 >> 2);
- *p++ = (b2 << 6) | b3;
- }
- dlen = full * 3;
- switch (rem) {
- case 1:
- b0 = asciitable [data [offset++]];
- b1 = asciitable [data [offset++]];
- b2 = asciitable [data [offset++]];
-
- *p++ = (b0 << 2) | (b1 >> 4);
- *p++ = (b1 << 4) | (b2 >> 2);
- dlen += 2;
- break;
- case 2:
- b0 = asciitable [data [offset++]];
- b1 = asciitable [data [offset++]];
-
- *p++ = (b0 << 2) | (b1 >> 4);
- dlen++;
- break;
- }
- *rlen = dlen;
- return data;
-}
-
-enum {
- DER_INTEGER = 2,
- DER_BITSTRING = 3,
- DER_NULL = 5,
- DER_OBJID = 6,
- DER_SEQUENCE = 16,
- DER_INVALID = -1,
- DER_END = -2
-};
-
-static int
-der_get_next (guchar *data, int dlen, int offset, int *len, guchar **rdata)
-{
- int i, l, type, val;
-
- if (offset + 1 >= dlen)
- return DER_END;
-
- type = data [offset++] & 0x1f;
- if (data [offset] == 0x80) /* not supported */
- return DER_INVALID;
- l = 0;
- if (data [offset] & 0x80) {
- val = data [offset++] & 0x7f;
- for (i = 0; i < val; ++i) {
- l = (l << 8) | data [offset++];
- }
- } else {
- l = data [offset++];
- }
- *len = l;
- *rdata = data + offset;
- return type;
-}
-
-static void
-dump_asn1 (guchar *key, int len) {
- int type, offset, elen;
- guchar *edata;
-
- offset = 0;
- while ((type = der_get_next (key, len, offset, &elen, &edata)) >= 0) {
- switch (type) {
- case DER_SEQUENCE:
- g_print ("seq (%d) at %d\n", elen, offset);
- dump_asn1 (edata, elen);
- offset = elen + edata - key;
- break;
- case DER_BITSTRING:
- g_print ("bits (%d) at %p + %d\n", elen, edata, offset);
- dump_asn1 (edata + 1, elen);
- offset = 1 + elen + edata - key;
- break;
- case DER_INTEGER:
- g_print ("int (%d) at %d\n", elen, offset);
- offset = elen + edata - key;
- break;
- case DER_NULL:
- g_print ("null (%d) at %d\n", elen, offset);
- offset = elen + edata - key;
- break;
- case DER_OBJID:
- g_print ("objid (%d) at %d\n", elen, offset);
- offset = elen + edata - key;
- break;
- default:
- return;
- }
- }
-}
-
-static guint32
-get_der_int (guchar *data, int len)
-{
- guint32 val = 0;
- int i;
- for (i = 0; i < len; ++i)
- val = (val << 8) | data [i];
- return val;
-}
-
-static void
-mem_reverse (guchar *p, int len) {
- int i, t;
-
- for (i = 0; i < len/2; ++i) {
- t = p [i];
- p [i] = p [len - i - 1];
- p [len - i - 1] = t;
- }
-}
-
-static int
-convert_der_key (guchar *key, int len, guchar **ret, int *retlen)
-{
- int type, offset, val, elen;
- guchar *r, *edata;
-
- offset = 0;
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type != DER_SEQUENCE)
- return 1;
- key = edata;
- len = elen;
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type == DER_INTEGER) {
- int i;
- guchar *ints [6];
- int lengths [6];
- guchar *p;
- /* a private RSA key */
- val = get_der_int (edata, elen);
- if (val != 0)
- return 2;
- offset = elen + edata - key;
- /* the modulus */
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type != DER_INTEGER)
- return 2;
- offset = elen + edata - key;
- if ((elen & 1) && *edata == 0) {
- edata ++;
- elen--;
- }
- r = g_new0 (guchar, elen*4 + elen/2 + 20);
- r [0] = 0x7; r [1] = 0x2; r [5] = 0x24;
- r [8] = 0x52; r [9] = 0x53; r [10] = 0x41; r [11] = 0x32;
- *(guint32*)(r + 12) = elen * 8;
- memcpy (r + 20, edata, elen);
- mem_reverse (r + 20, elen);
- p = r + 20 + elen;
- /* the exponent */
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type != DER_INTEGER)
- return 2;
- offset = elen + edata - key;
- val = get_der_int (edata, elen);
- *(guint32*)(r + 16) = val;
- for (i = 0; i < 6; i++) {
- type = der_get_next (key, len, offset, &elen, &edata);
- if (type != DER_INTEGER)
- return 2;
- offset = elen + edata - key;
- if ((elen & 1) && *edata == 0) {
- edata++;
- elen--;
- }
- ints [i] = edata;
- lengths [i] = elen;
- g_print ("len: %d\n", elen);
- }
- /* prime1 */
- g_print ("prime1 at %d (%d)\n", p-r, lengths [1]);
- memcpy (p, ints [1], lengths [1]);
- mem_reverse (p, lengths [1]);
- p += lengths [1];
- /* prime2 */
- g_print ("prime2 at %d (%d)\n", p-r, lengths [2]);
- memcpy (p, ints [2], lengths [2]);
- mem_reverse (p, lengths [2]);
- p += lengths [2];
- /* exponent1 */
- g_print ("exp1 at %d (%d)\n", p-r, lengths [3]);
- memcpy (p, ints [3], lengths [3]);
- mem_reverse (p, lengths [3]);
- p += lengths [3];
- /* exponent2 */
- g_print ("exp2 at %d (%d)\n", p-r, lengths [4]);
- memcpy (p, ints [4], lengths [4]);
- mem_reverse (p, lengths [4]);
- p += lengths [4];
- /* coeff */
- g_print ("coeff at %d (%d)\n", p-r, lengths [5]);
- memcpy (p, ints [5], lengths [5]);
- mem_reverse (p, lengths [5]);
- p += lengths [5];
- /* private exponent */
- g_print ("prive at %d (%d)\n", p-r, lengths [0]);
- memcpy (p, ints [0], lengths [0]);
- mem_reverse (p, lengths [0]);
- p += lengths [0];
- *ret = r;
- *retlen = p-r;
- return 0;
- }
- return 1;
-}
-
-static int
-convert_format (const char *from, const char *outfile) {
- guchar *key, *bindata, *keyout;
- gsize len;
- int binlen, ret, lenout;
- FILE *file;
-
- if (!g_file_get_contents (from, (gchar**) &key, &len, NULL)) {
- printf ("Cannot load file: %s\n", from);
- return 2;
- }
-
- if (*key == 0 || *key == 0x24) {
- g_free (key);
- printf ("Cannot convert to pem format yet\n");
- return 2;
- }
- bindata = pem_decode (key, len, &binlen);
- if (!(file = fopen (outfile, "wb"))) {
- g_free (key);
- printf ("Cannot open output file: %s\n", outfile);
- return 2;
- }
- dump_asn1 (bindata, binlen);
- ret = convert_der_key (bindata, binlen, &keyout, &lenout);
- if (!ret) {
- fwrite (keyout, lenout, 1, file);
- g_free (keyout);
- } else {
- printf ("Cannot convert key\n");
- }
- fclose (file);
- g_free (key);
- return ret;
-}
-
-static int
-get_digest (const char *from, const char *outfile)
-{
- guchar *ass;
- guchar digest [20];
- gsize len;
- guint32 snpos, snsize;
- FILE *file;
- MonoImage *image;
- MonoSHA1Context sha1;
-
- image = mono_image_open (from, NULL);
- if (!image) {
- printf ("Cannot open image file: %s\n", from);
- return 2;
- }
- snpos = mono_image_strong_name_position (image, &snsize);
- if (!snpos) {
- /*printf ("%s does not represent a strongly named assembly\n", from);
- mono_image_close (image);
- return 2;*/
- snsize = 0;
- }
-
- if (!g_file_get_contents (from, (gchar**) &ass, &len, NULL)) {
- printf ("Cannot load file: %s\n", from);
- mono_image_close (image);
- return 2;
- }
- /*
- * FIXME: we may need to set the STRONGNAMESIGNED flag in the cli header
- * before taking the sha1 digest of the image.
- */
- mono_sha1_init (&sha1);
- mono_sha1_update (&sha1, ass, snpos);
- mono_sha1_update (&sha1, ass + snpos + snsize, len - snsize - snpos);
- mono_sha1_final (&sha1, digest);
-
- mono_image_close (image);
- g_free (ass);
- if (!(file = fopen (outfile, "wb"))) {
- printf ("Cannot open output file: %s\n", outfile);
- return 2;
- }
- fwrite (digest, 20, 1, file);
- fclose (file);
- return 0;
-}
-
-static void
-help (int err) {
- printf ("monosn: Mono Strong Name Utility\nUsage: monosn option [arguments]\n");
- printf ("Available options:\n");
- printf ("\t-C keyin keyout Convert key file format from PEM to cryptoAPI (or the reverse).\n");
- printf ("\t-e assembly file Extract the public key from assembly to file.\n");
- printf ("\t-E assembly file Extract the strong name from assembly to file.\n");
- printf ("\t-r assembly file Extract the sha1 digest from assembly to file.\n");
- printf ("\t-t[p] file Display the public key token from file.\n");
- printf ("\t-T[p] assembly Display the public key token from assembly.\n");
- exit (err);
-}
-
-int
-main (int argc, char *argv[]) {
- int opt;
-
- if (argc < 2 || argv [1] [0] != '-')
- help (1);
-
- opt = argv [1] [1];
- switch (opt) {
- case 'C':
- if (argc != 4)
- help (1);
- return convert_format (argv [2], argv [3]);
- case 'e':
- if (argc != 4)
- help (1);
- return extract_data_to_file (1, argv [2], argv [3]);
- case 'E':
- if (argc != 4)
- help (1);
- return extract_data_to_file (0, argv [2], argv [3]);
- case 'h':
- case '?':
- help (0);
- return 0;
- case 'r':
- if (argc != 4)
- help (1);
- return get_digest (argv [2], argv [3]);
- case 't':
- if (argc != 3)
- help (1);
- return show_token (argv [2], 0, argv [1] [2] == 'p');
- case 'T':
- if (argc != 3)
- help (1);
- return show_token (argv [2], 1, argv [1] [2] == 'p');
- default:
- help (1);
- }
- return 0;
-}
-