2014-07-01 19:02:52 +04:00
/* Parse a Microsoft Individual Code Signing blob
*
* Copyright ( C ) 2014 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation ; either version
* 2 of the Licence , or ( at your option ) any later version .
*/
# define pr_fmt(fmt) "MSCODE: "fmt
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/err.h>
# include <linux/oid_registry.h>
# include <crypto/pkcs7.h>
# include "verify_pefile.h"
# include "mscode-asn1.h"
/*
* Parse a Microsoft Individual Code Signing blob
*/
2016-04-06 18:14:24 +03:00
int mscode_parse ( void * _ctx , const void * content_data , size_t data_len ,
size_t asn1hdrlen )
2014-07-01 19:02:52 +04:00
{
2016-04-06 18:14:24 +03:00
struct pefile_context * ctx = _ctx ;
2014-07-01 19:02:52 +04:00
2016-04-06 18:14:24 +03:00
content_data - = asn1hdrlen ;
data_len + = asn1hdrlen ;
2014-07-01 19:02:52 +04:00
pr_devel ( " Data: %zu [%*ph] \n " , data_len , ( unsigned ) ( data_len ) ,
content_data ) ;
return asn1_ber_decoder ( & mscode_decoder , ctx , content_data , data_len ) ;
}
/*
* Check the content type OID
*/
int mscode_note_content_type ( void * context , size_t hdrlen ,
unsigned char tag ,
const void * value , size_t vlen )
{
enum OID oid ;
oid = look_up_OID ( value , vlen ) ;
if ( oid = = OID__NR ) {
char buffer [ 50 ] ;
sprint_oid ( value , vlen , buffer , sizeof ( buffer ) ) ;
pr_err ( " Unknown OID: %s \n " , buffer ) ;
return - EBADMSG ;
}
2014-07-08 21:10:46 +04:00
/*
* pesign utility had a bug where it was putting
* OID_msIndividualSPKeyPurpose instead of OID_msPeImageDataObjId
* So allow both OIDs .
*/
if ( oid ! = OID_msPeImageDataObjId & &
oid ! = OID_msIndividualSPKeyPurpose ) {
2014-07-01 19:02:52 +04:00
pr_err ( " Unexpected content type OID %u \n " , oid ) ;
return - EBADMSG ;
}
return 0 ;
}
/*
* Note the digest algorithm OID
*/
int mscode_note_digest_algo ( void * context , size_t hdrlen ,
unsigned char tag ,
const void * value , size_t vlen )
{
struct pefile_context * ctx = context ;
char buffer [ 50 ] ;
enum OID oid ;
oid = look_up_OID ( value , vlen ) ;
switch ( oid ) {
case OID_md4 :
2016-03-04 00:49:27 +03:00
ctx - > digest_algo = " md4 " ;
2014-07-01 19:02:52 +04:00
break ;
case OID_md5 :
2016-03-04 00:49:27 +03:00
ctx - > digest_algo = " md5 " ;
2014-07-01 19:02:52 +04:00
break ;
case OID_sha1 :
2016-03-04 00:49:27 +03:00
ctx - > digest_algo = " sha1 " ;
2014-07-01 19:02:52 +04:00
break ;
case OID_sha256 :
2016-03-04 00:49:27 +03:00
ctx - > digest_algo = " sha256 " ;
2014-07-01 19:02:52 +04:00
break ;
2015-08-30 18:59:57 +03:00
case OID_sha384 :
2016-03-04 00:49:27 +03:00
ctx - > digest_algo = " sha384 " ;
2015-08-30 18:59:57 +03:00
break ;
case OID_sha512 :
2016-03-04 00:49:27 +03:00
ctx - > digest_algo = " sha512 " ;
2015-08-30 18:59:57 +03:00
break ;
case OID_sha224 :
2016-03-04 00:49:27 +03:00
ctx - > digest_algo = " sha224 " ;
2015-08-30 18:59:57 +03:00
break ;
2014-07-01 19:02:52 +04:00
case OID__NR :
sprint_oid ( value , vlen , buffer , sizeof ( buffer ) ) ;
pr_err ( " Unknown OID: %s \n " , buffer ) ;
return - EBADMSG ;
default :
pr_err ( " Unsupported content type: %u \n " , oid ) ;
return - ENOPKG ;
}
return 0 ;
}
/*
* Note the digest we ' re guaranteeing with this certificate
*/
int mscode_note_digest ( void * context , size_t hdrlen ,
unsigned char tag ,
const void * value , size_t vlen )
{
struct pefile_context * ctx = context ;
2016-04-06 18:14:24 +03:00
ctx - > digest = kmemdup ( value , vlen , GFP_KERNEL ) ;
2016-07-18 02:10:47 +03:00
if ( ! ctx - > digest )
return - ENOMEM ;
ctx - > digest_len = vlen ;
return 0 ;
2014-07-01 19:02:52 +04:00
}