Skip to content

Commit

Permalink
Add support for creating detached cms signatures
Browse files Browse the repository at this point in the history
See rfc2630 for documentation. This is also what is used to sign
linux kernel modules.
  • Loading branch information
mlschroe committed Oct 27, 2022
1 parent 38e6c18 commit 455bcf8
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 116 deletions.
4 changes: 2 additions & 2 deletions appx.c
Expand Up @@ -126,7 +126,7 @@ appx_read(struct appxdata *appxdata, int fd, char *filename, time_t t)

/* create signedattrs */
x509_init(&appxdata->cb_signedattrs);
x509_spcsignedattrs(&appxdata->cb_signedattrs, hash_read(&ctx), 32, t);
x509_spcsignedattrs(&appxdata->cb_signedattrs, hash_read(&ctx), hash_len(), t);
return 1;
}

Expand All @@ -137,7 +137,7 @@ appx_write(struct appxdata *appxdata, int outfd, int fd, struct x509 *cert, unsi
struct x509 cb;

x509_init(&cb);
x509_pkcs7(&cb, &appxdata->cb_content, &appxdata->cb_signedattrs, sig, siglen, cert, othercerts);
x509_pkcs7(&cb, &appxdata->cb_content, &appxdata->cb_signedattrs, sig, siglen, cert, othercerts, 0);
/* add file magic */
x509_insert(&cb, 0, p7xmagic, sizeof(p7xmagic));
if (appxsig2stdout)
Expand Down
11 changes: 11 additions & 0 deletions hash.c
Expand Up @@ -1110,3 +1110,14 @@ unsigned char *hash_read(HASH_CONTEXT *c)
return 0;
}

int hash_len()
{
if (hashalgo == HASH_SHA1)
return 20;
else if (hashalgo == HASH_SHA256)
return 32;
else if (hashalgo == HASH_SHA512)
return 64;
return 0;
}

9 changes: 7 additions & 2 deletions inc.h
Expand Up @@ -77,6 +77,7 @@ void hash_init(HASH_CONTEXT *c);
void hash_write(HASH_CONTEXT *c, const unsigned char *b, size_t l);
void hash_final(HASH_CONTEXT *c);
unsigned char *hash_read(HASH_CONTEXT *c);
int hash_len(void);

/* base64.c */
void printr64(FILE *f, const byte *str, int len);
Expand Down Expand Up @@ -118,11 +119,15 @@ byte *getrawopensslsig(byte *sig, int sigl, int *lenp);
void certsizelimit(char *s, int l);

int x509_addpem(struct x509 *cb, char *buf, char *type);
void x509_signedattrs(struct x509 *cb, unsigned char *digest, int digestlen, time_t signtime);
void x509_pkcs7(struct x509 *cb, struct x509 *contentinfo, struct x509 *signedattrs, unsigned char *sig, int siglen, struct x509 *cert, struct x509 *othercerts, int flags);
int x509_cert2pubalgo(struct x509 *cert);

int x509_spccontentinfo(struct x509 *cb, unsigned char *digest, int digestlen);
void x509_spcsignedattrs(struct x509 *cb, unsigned char *digest, int digestlen, time_t signtime);
void x509_pkcs7(struct x509 *cb, struct x509 *contentinfo, struct x509 *signedattrs, unsigned char *sig, int siglen, struct x509 *cert, struct x509 *othercerts);
int x509_cert2pubalgo(struct x509 *cert);

#define X509_PKCS7_USE_KEYID (1 << 0)
#define X509_PKCS7_NO_CERTS (1 << 1)

/* zip.c */
struct zip {
Expand Down
75 changes: 59 additions & 16 deletions sign.c
Expand Up @@ -78,10 +78,12 @@ int appxsig2stdout = 0;
#define MODE_APPIMAGESIGN 11
#define MODE_APPXSIGN 12
#define MODE_HASHFILE 13
#define MODE_CMSSIGN 14

static const char *const modes[] = {
"?", "rpm sign", "clear sign", "detached sign", "keyid", "pubkey", "keygen", "keyextend",
"raw detached sign" "raw openssl sign" "cert create", "appimage sign", "appx sign", "hashfile"
"raw detached sign" "raw openssl sign" "cert create", "appimage sign", "appx sign", "hashfile",
"cms sign"
};

static void
Expand Down Expand Up @@ -231,6 +233,7 @@ sign(char *filename, int isfilter, int mode)
int getbuildtime = 0;
unsigned char *v4sigtrail = 0;
int v4sigtraillen = 0;
struct x509 cms_signedattrs;

if (mode == MODE_UNSET)
{
Expand All @@ -257,6 +260,25 @@ sign(char *filename, int isfilter, int mode)
exit(1);
}

/* make sure we have a cert for appx/cms sign */
if (mode == MODE_APPXSIGN || mode == MODE_CMSSIGN)
{
int pubalgo;
if (!cert.len)
{
fprintf(stderr, "need a cert for %s\n", modes[mode]);
exit(1);
}
pubalgo = x509_cert2pubalgo(&cert);
if (assertpubalgo < 0)
assertpubalgo = pubalgo;
if (assertpubalgo != pubalgo)
{
fprintf(stderr, "pubkey algorithm does not match cert\n");
exit(1);
}
}

/* open input file */
if (isfilter)
fd = 0;
Expand All @@ -279,6 +301,8 @@ sign(char *filename, int isfilter, int mode)
sprintf(outfilename, "%s.asc", filename);
else if (mode == MODE_RAWDETACHEDSIGN || mode == MODE_RAWOPENSSLSIGN)
sprintf(outfilename, "%s.sig", filename);
else if (mode == MODE_CMSSIGN)
sprintf(outfilename, "%s.p7s", filename);
else
{
sprintf(outfilename, "%s.sIgN%d", filename, getpid());
Expand Down Expand Up @@ -334,20 +358,6 @@ sign(char *filename, int isfilter, int mode)
}
else if (mode == MODE_APPXSIGN)
{
int pubalgo;
if (!cert.len)
{
fprintf(stderr, "need a cert for appx signing\n");
exit(1);
}
pubalgo = x509_cert2pubalgo(&cert);
if (assertpubalgo < 0)
assertpubalgo = pubalgo;
if (assertpubalgo != pubalgo)
{
fprintf(stderr, "pubkey algorithm does not match cert\n");
exit(1);
}
if (appx_read(&appxdata, fd, filename, signtime) == 0)
{
fprintf(isfilter ? stderr : stdout, "%s: already signed\n", filename);
Expand Down Expand Up @@ -401,14 +411,26 @@ sign(char *filename, int isfilter, int mode)
hash_write(&ctx, buf, l);
}

if (mode == MODE_CMSSIGN)
{
x509_init(&cms_signedattrs);
if (signtime)
{
hash_final(&ctx);
x509_signedattrs(&cms_signedattrs, hash_read(&ctx), hash_len(), signtime);
hash_init(&ctx);
hash_write(&ctx, cms_signedattrs.buf, cms_signedattrs.len);
}
}

if (verbose && mode != MODE_KEYID)
{
if (*user)
fprintf(isfilter ? stderr : stdout, "%s %s user %s\n", modes[mode], filename, user);
else
fprintf(isfilter ? stderr : stdout, "%s %s\n", modes[mode], filename);
}
if (mode == MODE_RAWOPENSSLSIGN || mode == MODE_APPXSIGN)
if (mode == MODE_RAWOPENSSLSIGN || mode == MODE_APPXSIGN || mode == MODE_CMSSIGN)
{
sigtrail[0] = pkcs1pss ? 0xbc : 0x00;
sigtrail[1] = sigtrail[2] = sigtrail[3] = sigtrail[4] = 0; /* time does not matter */
Expand Down Expand Up @@ -647,6 +669,25 @@ sign(char *filename, int isfilter, int mode)
appx_free(&appxdata);
free(rawssl);
}
else if (mode == MODE_CMSSIGN)
{
struct x509 cb;
int rawssllen = 0;
int sigl;
byte *sig = pkg2sig(buf + 6, outl, &sigl);
byte *rawssl = getrawopensslsig(sig, sigl, &rawssllen);
if (!rawssl)
{
if (!isfilter)
unlink(outfilename);
exit(1);
}
x509_init(&cb);
x509_pkcs7(&cb, 0, (cms_signedattrs.len ? &cms_signedattrs : 0), rawssl, rawssllen, &cert, &othercerts, 0);
fwrite(cb.buf, 1, cb.len, fout);
x509_free(&cb);
x509_free(&cms_signedattrs);
}
else
fwrite(buf + 6, 1, outl, fout);

Expand Down Expand Up @@ -1641,6 +1682,8 @@ main(int argc, char **argv)
mode = MODE_APPXSIGN;
appxsig2stdout = 1;
}
else if (!strcmp(opt, "--cmssign"))
mode = MODE_CMSSIGN;
else if (!strcmp(opt, "--"))
break;
else
Expand Down

0 comments on commit 455bcf8

Please sign in to comment.