diff --git a/CHANGELOG.md b/CHANGELOG.md index 702a82a1..719952ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ======= +# [2.3.0] +### Added +- added the ability to specify a buffer length, when performing HMAC key check values (default is 0). + # [2.2.0] ### Added - p11kcv will compute a Key Check Value on `CK_GENERIC_SECRET` keys as well. These are mapped to HMAC-SHA256. diff --git a/configure.ac b/configure.ac index 0e6e52e0..3f9fdd16 100644 --- a/configure.ac +++ b/configure.ac @@ -14,7 +14,7 @@ dnl limitations under the License. AC_PREREQ([2.64]) -AC_INIT([pkcs11-tools], [2.2.0], [https://github.com/Mastercard/pkcs11-tools/issues], [pkcs11-tools], [https://github.com/Mastercard/pkcs11-tools]) +AC_INIT([pkcs11-tools], [2.3.0], [https://github.com/Mastercard/pkcs11-tools/issues], [pkcs11-tools], [https://github.com/Mastercard/pkcs11-tools]) AC_CONFIG_MACRO_DIR([m4]) dnl adding AM_MAINTAINER_MODE to address autotools issues with git diff --git a/docs/MANUAL.md b/docs/MANUAL.md index 775f7a0d..7d761484 100644 --- a/docs/MANUAL.md +++ b/docs/MANUAL.md @@ -518,7 +518,12 @@ For generating HMAC key on nCipher, you need to use one of the following key typ using `p11keygen`, it is possible to generate a session key and wrap it immediately under one or several wrapping keys. To achieve this, you simply need to add the `-W` optional parameter, followed by the wrapping parameters string, as explained in `p11wrap`. Note that by default, `p11keygen` will attempt to store a copy of the session key on the token. To prevent this (some PKCS\#11 library do not support this), add the `-r` optional parameter. ## p11kcv -Computes the key check value of a symmetric key and prints it. This will work only on symmetric keys (`des` and `aes` keys). +Computes the key check value of a symmetric key and prints it. This will work only on secret keys, i.e. DES, AES and HMAC keys. + +The key check value is computed as follows: +- For DES keys, it performs a a signature (MACing) or an encryption on a block of 8 zeroized bytes, and outputting the 3 first ones. +- For AES keys, it performs a a signature (MACing) or an encryption on a block of 16 zeroized bytes, and outputting the 3 first ones. +- For HMAC keys, the key check value is computed by HMACing a null-length buffer. Alternatively, it is possible to specify a length, using the `-b` optional argument, in which case a zeroized buffer of the specified lenght is used as input to the HMAC. ## p11req Generate a PKCS\#10 CSR. Important options are: diff --git a/include/pkcs11lib.h b/include/pkcs11lib.h index 971cd20b..c9c8a8ca 100644 --- a/include/pkcs11lib.h +++ b/include/pkcs11lib.h @@ -684,7 +684,8 @@ func_rc pkcs11_info_ecsupport(pkcs11Context *p11Context); func_rc pkcs11_change_object_attributes(pkcs11Context *p11Context, char *label, CK_ATTRIBUTE *attr, size_t cnt, int interactive ); /* kcv functions */ -void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ); +#define MAX_KCV_CLEARTEXT_SIZE 256 +void pkcs11_display_kcv( pkcs11Context *p11Context, char *label, unsigned hmacdatasize ); /* wrap/unwrap functions */ func_rc pkcs11_prepare_wrappingctx(wrappedKeyCtx *wctx, char *wrappingjob); diff --git a/lib/pkcs11_kcv.c b/lib/pkcs11_kcv.c index 9abcb321..c05841ce 100644 --- a/lib/pkcs11_kcv.c +++ b/lib/pkcs11_kcv.c @@ -33,13 +33,17 @@ /* target must point to a location with at least 3 bytes left */ -void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ) +void pkcs11_display_kcv( pkcs11Context *p11Context, char *label, unsigned hmacdatasize ) { pkcs11Search *search=NULL; pkcs11IdTemplate *idtmpl=NULL; CK_OBJECT_HANDLE *hndl_array=NULL; + + if(hmacdatasize>MAX_KCV_CLEARTEXT_SIZE) { + fprintf(stderr, "Invalid HMAC block size specified (%d), must be between 0 and %d\n", hmacdatasize, MAX_KCV_CLEARTEXT_SIZE ); + } /* trick: we treat "cert", "pubk", "prvk", "seck" and "data" in front of the templating system */ /* so these specific labels can be used as shortcut for the corresponding object classes */ @@ -91,9 +95,9 @@ void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ) if( attrs!=NULL) { if (pkcs11_read_attr_from_handle (attrs, hndl_array[j]) == CK_TRUE) { CK_RV rv; - CK_BYTE cleartext[16]; - CK_BYTE encrypted[64]; - CK_ULONG cleartext_len, encrypted_len; + CK_BYTE cleartext[MAX_KCV_CLEARTEXT_SIZE]; + CK_BYTE processed[64]; + CK_ULONG cleartext_len, processed_len; CK_MECHANISM des_ecb = { CKM_DES_ECB, NULL_PTR, 0 }; CK_MECHANISM des3_ecb = { CKM_DES3_ECB, NULL_PTR, 0 }; @@ -130,7 +134,7 @@ void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ) case CKK_DES: mechanism = &des_ecb; cleartext_len = 8L; - encrypted_len = 8L; + processed_len = 8L; keytypestr = "DES, single length"; whattodo=encrypt; break; @@ -138,7 +142,7 @@ void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ) case CKK_DES2: mechanism = &des3_ecb; cleartext_len = 8L; - encrypted_len = 8L; + processed_len = 8L; keytypestr = "3DES, double length"; whattodo=encrypt; break; @@ -146,7 +150,7 @@ void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ) case CKK_DES3: mechanism = &des3_ecb; cleartext_len = 8L; - encrypted_len = 8L; + processed_len = 8L; keytypestr = "3DES, triple length"; whattodo=encrypt; break; @@ -154,15 +158,15 @@ void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ) case CKK_AES: mechanism = &aes_ecb; cleartext_len = 16L; - encrypted_len = 16L; + processed_len = 16L; keytypestr = "AES"; whattodo=encrypt; break; case CKK_SHA_1_HMAC: mechanism = &sha1_hmac; - cleartext_len = 0L; - encrypted_len = 20L; + cleartext_len = hmacdatasize; + processed_len = 20L; keytypestr = "HMAC(SHA1)"; whattodo=sign; break; @@ -170,24 +174,24 @@ void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ) case CKK_SHA256_HMAC: case CKK_GENERIC_SECRET: mechanism = &sha256_hmac; - cleartext_len = 0L; - encrypted_len = 32L; + cleartext_len = hmacdatasize; + processed_len = 32L; keytypestr = "HMAC(SHA256)"; whattodo=sign; break; case CKK_SHA384_HMAC: mechanism = &sha384_hmac; - cleartext_len = 0L; - encrypted_len = 48L; + cleartext_len = hmacdatasize; + processed_len = 48L; keytypestr = "HMAC(SHA384)"; whattodo=sign; break; case CKK_SHA512_HMAC: mechanism = &sha512_hmac; - cleartext_len = 0L; - encrypted_len = 64L; + cleartext_len = hmacdatasize; + processed_len = 64L; keytypestr = "HMAC(SHA384)"; whattodo=sign; break; @@ -220,13 +224,13 @@ void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ) p11Context->FunctionList.C_Encrypt ( p11Context->Session, cleartext, cleartext_len, - encrypted, - &encrypted_len ) : + processed, + &processed_len ) : p11Context->FunctionList.C_Sign ( p11Context->Session, cleartext, cleartext_len, - encrypted, - &encrypted_len ); + processed, + &processed_len ); if(rv!=CKR_OK) { pkcs11_error(rv, whattodo == encrypt ? "C_Encrypt" : "C_Sign"); pkcs11_delete_attrlist(attrs); @@ -237,9 +241,9 @@ void pkcs11_display_kcv( pkcs11Context *p11Context, char *label ) printf("%-*s: KCV = %02.2x%02.2x%02.2x (%s)\n", LABEL_WIDTH, buffer, - encrypted[0], - encrypted[1], - encrypted[2], + processed[0], + processed[1], + processed[2], keytypestr); } pkcs11_delete_attrlist(attrs); diff --git a/src/p11kcv.c b/src/p11kcv.c index 0b5ce5c1..5f8fb872 100644 --- a/src/p11kcv.c +++ b/src/p11kcv.c @@ -37,6 +37,8 @@ void print_usage(char *); int main( int argc, char **argv); + + void print_usage(char *progname) { fprintf( stderr, @@ -50,6 +52,7 @@ void print_usage(char *progname) " -t : if present, -s option is ignored\n" " -p | :::exec: | :::nologin\n" " -S : login with SO privilege\n" + " -b : size of buffer to HMAC, for HMAC keys (max: %d, default: 0)\n" " -h : print usage information\n" " -V : print version information\n" "|\n" @@ -86,7 +89,8 @@ void print_usage(char *progname) " PKCS11PASSWORD : password\n" " overriden by option -p\n" "\n" - , pkcs11_ll_basename(progname) ); + , pkcs11_ll_basename(progname), + MAX_KCV_CLEARTEXT_SIZE); exit( RC_ERROR_USAGE ); } @@ -105,6 +109,7 @@ int main( int argc, char ** argv ) int interactive = 1; char * tokenlabel = NULL; int so=0; + unsigned hmacdatasize = 0; pkcs11Context * p11Context = NULL; func_rc retcode = rc_error_usage; @@ -121,7 +126,7 @@ int main( int argc, char ** argv ) password = getenv("PKCS11PASSWORD"); /* get the command-line arguments */ - while ( ( argnum = getopt( argc, argv, "l:m:p:s:t:ShV" ) ) != -1 ) + while ( ( argnum = getopt( argc, argv, "l:m:p:s:t:Sb:hV" ) ) != -1 ) { switch ( argnum ) { @@ -149,6 +154,10 @@ int main( int argc, char ** argv ) slot = -1; break; + case 'b': + hmacdatasize=strtoul(optarg, NULL, 10); + break; + case 'S': so=1; break; @@ -195,7 +204,7 @@ int main( int argc, char ** argv ) { char *label; for(label=argv[optind];optind