Skip to content

Commit

Permalink
Add kernel module sign support
Browse files Browse the repository at this point in the history
Note that you need to use '-T 0' to create a pkcs7 signature with
no signed attributes.
  • Loading branch information
mlschroe committed Nov 8, 2022
1 parent bfa97ef commit ded6f02
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 172 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ CFLAGS = -O3 -Wall -D_FILE_OFFSET_BITS=64 -g

all: sign

sign: sign.o hash.o base64.o pgp.o x509.o rpm.o appimage.o sock.o clearsign.o appx.o zip.o pe.o
sign: sign.o hash.o base64.o pgp.o x509.o rpm.o appimage.o sock.o clearsign.o appx.o zip.o pe.o ko.o

clean:
rm -f sign sign.o hash.o base64.o pgp.o x509.o rpm.o appimage.o sock.o clearsign.o appx.o zip.o pe.o
rm -f sign sign.o hash.o base64.o pgp.o x509.o rpm.o appimage.o sock.o clearsign.o appx.o zip.o pe.o ko.o
test:
prove t/*.t
20 changes: 20 additions & 0 deletions appimage.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ perror_exit(const char *s)
exit(1);
}

int
appimage_read(char *filename, HASH_CONTEXT *ctx)
{
unsigned char appimagedigest[64]; /* sha256 sum */
char *digestfilename;
FILE *fp;

digestfilename = malloc(strlen(filename) + 8);
sprintf(digestfilename, "%s.digest", filename);
if ((fp = fopen(digestfilename, "r")) == 0 || 64 != fread(appimagedigest, 1, 64, fp))
{
perror(digestfilename);
exit(1);
}
fclose(fp);
free(digestfilename);
hash_write(ctx, appimagedigest, 64);
return 1;
}

void
appimage_write_signature(char *filename, byte *signature, int length)
{
Expand Down
72 changes: 43 additions & 29 deletions appx.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,6 @@

extern int appxsig2stdout;

static const unsigned char axmgsig[4] = { 0x41, 0x50, 0x50, 0x58 };
static const unsigned char axpcsig[4] = { 0x41, 0x58, 0x50, 0x43 };
static const unsigned char axcdsig[4] = { 0x41, 0x58, 0x43, 0x44 };
static const unsigned char axctsig[4] = { 0x41, 0x58, 0x43, 0x54 };
static const unsigned char axbmsig[4] = { 0x41, 0x58, 0x42, 0x4d };
static const unsigned char axcisig[4] = { 0x41, 0x58, 0x43, 0x49 };

static void
dosha256hash(int fd, unsigned long long size, unsigned char *out)
{
Expand Down Expand Up @@ -74,34 +67,28 @@ hashfileentry(struct zip *zip, int fd, char *fn, unsigned char *dig)
return zip_entry_datetime(entry);
}

int
appx_read(struct appxdata *appxdata, int fd, char *filename, time_t t)
static int
appx_create_contentinfo(struct appxdata *appxdata, int fd)
{
unsigned char digest[4 + (4 + 32) * 5];
int offset;
HASH_CONTEXT ctx;

if (hashalgo != HASH_SHA256)
static const unsigned char axmgsig[4] = { 0x41, 0x50, 0x50, 0x58 };
static const unsigned char axpcsig[4] = { 0x41, 0x58, 0x50, 0x43 };
static const unsigned char axcdsig[4] = { 0x41, 0x58, 0x43, 0x44 };
static const unsigned char axctsig[4] = { 0x41, 0x58, 0x43, 0x54 };
static const unsigned char axbmsig[4] = { 0x41, 0x58, 0x42, 0x4d };
static const unsigned char axcisig[4] = { 0x41, 0x58, 0x43, 0x49 };

/* rewind */
if (lseek(fd, 0, SEEK_SET) == (off_t)-1)
{
fprintf(stderr, "can only use sha256 for hashing\n");
perror("seek");
exit(1);
}
memset(appxdata, 0, sizeof(*appxdata));
zip_read(&appxdata->zip, fd);

if (zip_findentry(&appxdata->zip, "AppxSignature.p7x"))
return 0;

/* create digests */
memset(digest, 0, sizeof(digest));
memcpy(digest, axmgsig, 4);
memcpy(digest + 4, axpcsig, 4);
/* hash from start to central dir */
if (lseek(fd, 0, SEEK_SET) == (off_t)-1)
{
perror("seek");
exit(1);
}
dosha256hash(fd, appxdata->zip.cd_offset, digest + 8);
/* hash from central dir to end */
memcpy(digest + 40, axcdsig, 4);
Expand All @@ -115,18 +102,45 @@ appx_read(struct appxdata *appxdata, int fd, char *filename, time_t t)
/* zero AppxMetadata/CodeIntegrity.cat */
memcpy(digest + 148, axcisig, 4);

/* create spccontentinfo */
x509_init(&appxdata->cb_content);
offset = x509_appx_contentinfo(&appxdata->cb_content, digest, sizeof(digest));
return x509_appx_contentinfo(&appxdata->cb_content, digest, sizeof(digest));
}

static void
appx_create_signedattrs(struct appxdata *appxdata, int offset, time_t t)
{
HASH_CONTEXT ctx;

/* hash the spccontent */
hash_init(&ctx);
hash_write(&ctx, appxdata->cb_content.buf + offset, appxdata->cb_content.len - offset);
hash_final(&ctx);

/* create signedattrs */
x509_init(&appxdata->cb_signedattrs);
x509_appx_signedattrs(&appxdata->cb_signedattrs, hash_read(&ctx), hash_len(), t);
}

int
appx_read(struct appxdata *appxdata, int fd, char *filename, HASH_CONTEXT *ctx, time_t t)
{
int offset;

if (hashalgo != HASH_SHA256)
{
fprintf(stderr, "can only use sha256 for hashing\n");
exit(1);
}
memset(appxdata, 0, sizeof(*appxdata));
zip_read(&appxdata->zip, fd);

if (zip_findentry(&appxdata->zip, "AppxSignature.p7x"))
return 0;

/* create spccontentinfo */
offset = appx_create_contentinfo(appxdata, fd);
/* create signedattrs */
appx_create_signedattrs(appxdata, offset, t);
/* hash signedattrs */
hash_write(ctx, appxdata->cb_signedattrs.buf, appxdata->cb_signedattrs.len);
return 1;
}

Expand Down
9 changes: 7 additions & 2 deletions inc.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ void rpm_free(struct rpmdata *rd);
void rpm_writechecksums(struct rpmdata *rd, int chksumfilefd);

/* appimage.c */
int appimage_read(char *filename, HASH_CONTEXT *ctx);
void appimage_write_signature(char *filename, byte *signature, int length);

/* appx.c */
Expand All @@ -197,7 +198,7 @@ struct appxdata {
unsigned int datetime;
};

int appx_read(struct appxdata *appxdata, int fd, char *filename, time_t t);
int appx_read(struct appxdata *appxdata, int fd, char *filename, HASH_CONTEXT *ctx, time_t t);
void appx_write(struct appxdata *appxdata, int outfd, int fd, struct x509 *cert, unsigned char *sig, int siglen, struct x509 *othercerts);
void appx_free(struct appxdata *appxdata);

Expand All @@ -223,6 +224,10 @@ struct pedata {
unsigned int csum;
};

int pe_read(struct pedata *pedata, int fd, char *filename, time_t t);
int pe_read(struct pedata *pedata, int fd, char *filename, HASH_CONTEXT *hctx, time_t t);
void pe_write(struct pedata *pedata, int outfd, int fd, struct x509 *cert, unsigned char *sig, int siglen, struct x509 *othercerts);
void pe_free(struct pedata *pedata);

/* ko.c */
int ko_read(int fd, char *filename, HASH_CONTEXT *ctx);
void ko_write(int outfd, int fd, struct x509 *cb);
32 changes: 19 additions & 13 deletions pe.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ docopy(int outfd, int fd, const char *filename, unsigned int l)
}

static void
update_chksum(unsigned int pos, const unsigned char *b, int l, unsigned int *chkp)
update_chksum(unsigned int pos, const unsigned char *b, int l, unsigned int *csump)
{
unsigned int c = 0;
unsigned int c = *csump;
if (!l)
return;
if (l > 65536)
abort(); /* this might overflow */
if (l < 0 || l > 0x10000 * 2)
abort(); /* this can overflow */
if (pos & 1)
{
c = *b++ << 8;
Expand All @@ -67,8 +67,9 @@ update_chksum(unsigned int pos, const unsigned char *b, int l, unsigned int *chk
c += b[0] + (b[1] << 8);
if (l)
c += b[0];
c += *chkp;
*chkp = (c & 0xffff) + (c >> 16);
c = (c & 0xffff) + (c >> 16); /* fold to [0..0x1fffe] */
c = (c & 0xffff) + (c >> 16); /* fold to [0..0xffff] */
*csump = c;
}

static unsigned int
Expand Down Expand Up @@ -147,7 +148,7 @@ sectioncmp(const void *av, const void *bv)
}

int
pe_read(struct pedata *pedata, int fd, char *filename, time_t t)
pe_read(struct pedata *pedata, int fd, char *filename, HASH_CONTEXT *hctx, time_t t)
{
unsigned char hdr[4096];
HASH_CONTEXT ctx;
Expand Down Expand Up @@ -219,12 +220,15 @@ pe_read(struct pedata *pedata, int fd, char *filename, time_t t)
}
pedata->headersize = headersize;
pedata->c_off = stubsize + 24 + c_off;
/* clear checksum */
setle4(hdr + stubsize + 24 + 64, 0); /* clear checksum */
pedata->csum = 0;
pedata->csum_off = stubsize + 24 + 64;
memcpy(pedata->hdr, hdr, headersize);

if (hashalgo != HASH_SHA256)
{
fprintf(stderr, "can only use sha256 for hashing\n");
exit(1);
}
hash_init(&ctx);
hash_write(&ctx, hdr, stubsize + 24 + 64);
hash_write(&ctx, hdr + (stubsize + 24 + 68), c_off - 68);
Expand Down Expand Up @@ -273,7 +277,7 @@ pe_read(struct pedata *pedata, int fd, char *filename, time_t t)
{
int pad = 8 - (bytes_hashed & 7);
hash_write(&ctx, (const unsigned char *)"\0\0\0\0\0\0\0\0", pad);
update_chksum(bytes_hashed, (const unsigned char *)"\0\0\0\0\0\0\0\0", pad, &pedata->csum);
/* no need to call update_chksum() on zeros */
bytes_hashed += pad;
}
}
Expand All @@ -290,6 +294,9 @@ pe_read(struct pedata *pedata, int fd, char *filename, time_t t)
/* create signedattrs */
x509_init(&pedata->cb_signedattrs);
x509_pe_signedattrs(&pedata->cb_signedattrs, hash_read(&ctx), hash_len(), t);

/* hash signedattrs */
hash_write(hctx, pedata->cb_signedattrs.buf, pedata->cb_signedattrs.len);
return 1;
}

Expand All @@ -314,11 +321,10 @@ pe_write(struct pedata *pedata, int outfd, int fd, struct x509 *cert, unsigned c
setle4(pedata->hdr + pedata->c_off, pedata->filesize + filesizepad);
setle4(pedata->hdr + pedata->c_off + 4, cb.len);

/* update checksum with header and cert data, finalize checksum */
/* update checksum with header and cert data, put in header */
setle4(pedata->hdr + pedata->csum_off, 0);
update_chksum(0, pedata->hdr, pedata->headersize, &pedata->csum);
update_chksum(pedata->filesize + filesizepad, cb.buf, cb.len, &pedata->csum);
while (pedata->csum >= 0x10000)
pedata->csum = (pedata->csum & 0xffff) + (pedata->csum >> 16);
pedata->csum += pedata->filesize + filesizepad + cb.len;
setle4(pedata->hdr + pedata->csum_off, pedata->csum);

Expand Down
7 changes: 2 additions & 5 deletions rpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ rpm_readsigheader(struct rpmdata *rd, int fd, const char *filename)
return 1;
}

static int
static void
rpm_readheaderpayload(struct rpmdata *rd, int fd, char *filename, HASH_CONTEXT *ctx, HASH_CONTEXT *hctx, int getbuildtime)
{
byte buf[8192];
Expand Down Expand Up @@ -513,7 +513,6 @@ rpm_readheaderpayload(struct rpmdata *rd, int fd, char *filename, HASH_CONTEXT *
}
rd->buildtime = btbuf[0] << 24 | btbuf[1] << 16 | btbuf[2] << 8 | btbuf[3];
}
return 1;
}

int
Expand All @@ -522,9 +521,7 @@ rpm_read(struct rpmdata *rd, int fd, char *filename, HASH_CONTEXT *ctx, HASH_CON
memset(rd, 0, sizeof(*rd));
if (!rpm_readsigheader(rd, fd, filename))
return 0; /* already signed */
opensocket();
if (!rpm_readheaderpayload(rd, fd, filename, ctx, hctx, getbuildtime))
exit(1);
rpm_readheaderpayload(rd, fd, filename, ctx, hctx, getbuildtime);
return 1;
}

Expand Down
Loading

0 comments on commit ded6f02

Please sign in to comment.