VirtualBox

Changeset 95669 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 16, 2022 3:58:43 AM (2 years ago)
Author:
vboxsync
Message:

RTSignTool: Working on using certificates + private keys from the windows crypto stores. bugref:8691

Location:
trunk/src/VBox/Runtime/tools
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/tools/Makefile.kmk

    r93115 r95669  
    7777  bldRTSignTool_SOURCES = RTSignTool.cpp
    7878  bldRTSignTool_DEFS = IPRT_IN_BUILD_TOOL
     79  bldRTSignTool_LIBS.win = Crypt32.lib NCrypt.lib
    7980  bldRTSignTool_POST_CMDS.win = $(VBOX_SIGN_IMAGE_CMDS)
    8081  if defined(VBOX_WITH_DARWIN_R0_DARWIN_IMAGE_VERIFICATION) && defined(VBOX_SIGNING_MODE)
     
    214215 RTSignTool_SOURCES = RTSignTool.cpp
    215216 RTSignTool_LIBS = $(PATH_STAGE_LIB)/SUPR3$(VBOX_SUFF_LIB)
     217 RTSignTool_LIBS.win = Crypt32.lib NCrypt.lib
    216218
    217219 # RTTraceLogTool - Trace log collection and dissection tool.
  • trunk/src/VBox/Runtime/tools/RTSignTool.cpp

    r95659 r95669  
    4646#ifndef RT_OS_WINDOWS
    4747# include <iprt/formats/pecoff.h>
     48#else
     49# include <iprt/utf16.h>
    4850#endif
    4951#include <iprt/crypto/applecodesign.h>
     
    5557#include <iprt/crypto/spc.h>
    5658#include <iprt/crypto/tsp.h>
     59#include <iprt/cpp/ministring.h>
    5760#ifdef VBOX
    5861# include <VBox/sup.h> /* Certificates */
     
    6164# include <iprt/win/windows.h>
    6265# include <iprt/win/imagehlp.h>
     66# include <wincrypt.h>
     67# include <ncrypt.h>
    6368#endif
    6469
     
    6772*   Defined Constants And Macros                                                                                                 *
    6873*********************************************************************************************************************************/
    69 #define OPT_HASH_PAGES                  1000
    70 #define OPT_NO_HASH_PAGES               1001
    71 #define OPT_CERT_FILE                   1002
    72 #define OPT_KEY_FILE                    1003
    73 #define OPT_ADD_CERT                    1004
    74 
    75 #define OPT_TIMESTAMP_CERT_FILE         1010
    76 #define OPT_TIMESTAMP_KEY_FILE          1011
    77 #define OPT_TIMESTAMP_TYPE              1012
    78 #define OPT_TIMESTAMP_OVERRIDE          1016
     74#define OPT_OFF_CERT_FILE                   0       /**< signtool /f file */
     75#define OPT_OFF_CERT_SHA1                   1       /**< signtool /sha1 thumbprint */
     76#define OPT_OFF_CERT_SUBJECT                2       /**< signtool /n name */
     77#define OPT_OFF_CERT_STORE                  3       /**< signtool /s store */
     78#define OPT_OFF_CERT_STORE_MACHINE          4       /**< signtool /sm */
     79#define OPT_OFF_KEY_FILE                    5       /**< no signtool equivalent, other than maybe /f. */
     80#define OPT_OFF_KEY_PASSWORD                6       /**< signtool /p pass */
     81#define OPT_OFF_KEY_PASSWORD_FILE           7       /**< no signtool equivalent. */
     82#define OPT_OFF_KEY_NAME                    8       /**< signtool /kc  name */
     83#define OPT_OFF_KEY_PROVIDER                9       /**< signtool /csp name (CSP = cryptographic service provider) */
     84
     85#define OPT_CERT_KEY_SWITCH_CASES(a_Instance, a_uBase, a_chOpt, a_ValueUnion, a_rcExit) \
     86        case (a_uBase) + OPT_OFF_CERT_FILE: \
     87        case (a_uBase) + OPT_OFF_CERT_SHA1: \
     88        case (a_uBase) + OPT_OFF_CERT_SUBJECT: \
     89        case (a_uBase) + OPT_OFF_CERT_STORE: \
     90        case (a_uBase) + OPT_OFF_CERT_STORE_MACHINE: \
     91        case (a_uBase) + OPT_OFF_KEY_FILE: \
     92        case (a_uBase) + OPT_OFF_KEY_PASSWORD: \
     93        case (a_uBase) + OPT_OFF_KEY_PASSWORD_FILE: \
     94        case (a_uBase) + OPT_OFF_KEY_NAME: \
     95        case (a_uBase) + OPT_OFF_KEY_PROVIDER: \
     96            a_rcExit = a_Instance.handleOption((a_chOpt) - (a_uBase), &(a_ValueUnion)); \
     97            break
     98
     99#define OPT_CERT_KEY_GETOPTDEF_ENTRIES(a_szPrefix, a_uBase) \
     100        { a_szPrefix "cert-file",           (a_uBase) + OPT_OFF_CERT_FILE,          RTGETOPT_REQ_STRING }, \
     101        { a_szPrefix "cert-sha1",           (a_uBase) + OPT_OFF_CERT_SHA1,          RTGETOPT_REQ_STRING }, \
     102        { a_szPrefix "cert-subject",        (a_uBase) + OPT_OFF_CERT_SUBJECT,       RTGETOPT_REQ_STRING }, \
     103        { a_szPrefix "cert-store",          (a_uBase) + OPT_OFF_CERT_STORE,         RTGETOPT_REQ_STRING }, \
     104        { a_szPrefix "cert-machine-store",  (a_uBase) + OPT_OFF_CERT_STORE_MACHINE, RTGETOPT_REQ_NOTHING }, \
     105        { a_szPrefix "key-file",            (a_uBase) + OPT_OFF_KEY_FILE,           RTGETOPT_REQ_STRING }, \
     106        { a_szPrefix "key-password",        (a_uBase) + OPT_OFF_KEY_PASSWORD,       RTGETOPT_REQ_STRING }, \
     107        { a_szPrefix "key-password-file",   (a_uBase) + OPT_OFF_KEY_PASSWORD_FILE,  RTGETOPT_REQ_STRING }, \
     108        { a_szPrefix "key-name",            (a_uBase) + OPT_OFF_KEY_NAME,           RTGETOPT_REQ_STRING }, \
     109        { a_szPrefix "key-provider",        (a_uBase) + OPT_OFF_KEY_PROVIDER,       RTGETOPT_REQ_STRING }
     110
     111#define OPT_CERT_KEY_GETOPTDEF_COMPAT_ENTRIES(a_uBase) \
     112        { "/f",                             (a_uBase) + OPT_OFF_CERT_FILE,          RTGETOPT_REQ_STRING }, \
     113        { "/sha1",                          (a_uBase) + OPT_OFF_CERT_SHA1,          RTGETOPT_REQ_STRING }, \
     114        { "/n",                             (a_uBase) + OPT_OFF_CERT_SUBJECT,       RTGETOPT_REQ_STRING }, \
     115        { "/s",                             (a_uBase) + OPT_OFF_CERT_STORE,         RTGETOPT_REQ_STRING }, \
     116        { "/sm",                            (a_uBase) + OPT_OFF_CERT_STORE_MACHINE, RTGETOPT_REQ_NOTHING }, \
     117        { "/p",                             (a_uBase) + OPT_OFF_KEY_PASSWORD,       RTGETOPT_REQ_STRING }, \
     118        { "/kc",                            (a_uBase) + OPT_OFF_KEY_NAME,           RTGETOPT_REQ_STRING }, \
     119        { "/csp",                           (a_uBase) + OPT_OFF_KEY_PROVIDER,       RTGETOPT_REQ_STRING }
     120
     121#define OPT_CERT_KEY_SYNOPSIS(a_szPrefix) \
     122        "[" a_szPrefix "cert-file <file.pem|file.crt>] " \
     123        "[" a_szPrefix "cert-sha1 <fingerprint>] " \
     124        "[" a_szPrefix "cert-subject <part-name>] " \
     125        "[" a_szPrefix "cert-store <store>] " \
     126        "[" a_szPrefix "cert-machine-store] " \
     127        "[" a_szPrefix "key-file <file.pem|file.p12>] " \
     128        "[" a_szPrefix "key-password <password>] " \
     129        "[" a_szPrefix "key-password-file <file>|stdin] " \
     130        "[" a_szPrefix "key-name <name>] " \
     131        "[" a_szPrefix "key-provider <csp>] "
     132
     133#define OPT_HASH_PAGES                      1040
     134#define OPT_NO_HASH_PAGES                   1041
     135#define OPT_ADD_CERT                        1042
     136
     137#define OPT_TIMESTAMP_TYPE                  1043
     138#define OPT_TIMESTAMP_OVERRIDE              1044
    79139
    80140
     
    142202
    143203
    144 /**
    145  * Certificate w/ public key + private key pair for signing.
    146  */
    147 typedef struct SIGNTOOLKEYPAIR
    148 {
    149     RTCRX509CERTIFICATE     Cert;
    150     PCRTCRX509CERTIFICATE   pCertificate;
    151     RTCRKEY                 hPrivateKey;
    152 
    153     SIGNTOOLKEYPAIR()
    154         : pCertificate(NULL)
    155         , hPrivateKey(NIL_RTCRKEY)
    156     {
    157         RT_ZERO(Cert);
    158     }
    159 
    160     ~SIGNTOOLKEYPAIR()
    161     {
    162         if (hPrivateKey != NIL_RTCRKEY)
    163         {
    164             RTCrKeyRelease(hPrivateKey);
    165             hPrivateKey = NIL_RTCRKEY;
    166         }
    167         if (pCertificate == &Cert)
    168         {
    169             RTCrX509Certificate_Delete(&Cert);
    170             pCertificate = NULL;
    171         }
    172     }
    173 
    174     bool isComplete(void) const
    175     {
    176         return pCertificate && hPrivateKey != NIL_RTCRKEY;
    177     }
    178 
    179     bool isNull(void) const
    180     {
    181         return pCertificate == NULL && hPrivateKey == NIL_RTCRKEY;
    182     }
    183 } SIGNTOOLKEYPAIR;
    184 
    185 
    186204/*********************************************************************************************************************************
    187205*   Internal Functions                                                                                                           *
     
    193211static int HandleShowExeWorkerPkcs7Display(PSHOWEXEPKCS7 pThis, PRTCRPKCS7SIGNEDDATA pSignedData, size_t offPrefix,
    194212                                           PCRTCRPKCS7CONTENTINFO pContentInfo);
     213
     214
     215/*********************************************************************************************************************************
     216*   Certificate and Private Key Handling (options, ++).                                                                          *
     217*********************************************************************************************************************************/
     218/** @todo create a better fake certificate. */
     219const unsigned char g_abFakeCertificate[] =
     220{
     221    0x30, 0x82, 0x03, 0xb2, 0x30, 0x82, 0x02, 0x9a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x31, /* 0x00000000: 0...0..........1 */
     222    0xba, 0xd6, 0xbc, 0x5d, 0x9a, 0xe0, 0xb0, 0x4e, 0xd4, 0xfa, 0xcc, 0xfb, 0x47, 0x00, 0x5c, 0x30, /* 0x00000010: ...]...N....G.\0 */
     223    0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x71, /* 0x00000020: ...*.H........0q */
     224    0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x54, 0x69, 0x6d, 0x65, 0x73, /* 0x00000030: 1.0...U....Times */
     225    0x74, 0x61, 0x6d, 0x70, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x32, 0x31, 0x0c, /* 0x00000040: tamp Signing 21. */
     226    0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, 0x44, 0x65, 0x76, 0x31, 0x15, 0x30, 0x13, /* 0x00000050: 0...U....Dev1.0. */
     227    0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x70, /* 0x00000060: ..U....Test Comp */
     228    0x61, 0x6e, 0x79, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x53, 0x74, /* 0x00000070: any1.0...U....St */
     229    0x75, 0x74, 0x74, 0x67, 0x61, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, /* 0x00000080: uttgart1.0...U.. */
     230    0x0c, 0x02, 0x42, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x44, /* 0x00000090: ..BB1.0...U....D */
     231    0x45, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x31, 0x30, /* 0x000000a0: E0...00010100010 */
     232    0x31, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x31, 0x32, 0x33, 0x31, 0x32, 0x32, 0x35, 0x39, 0x35, 0x39, /* 0x000000b0: 1Z..361231225959 */
     233    0x5a, 0x30, 0x71, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x54, 0x69, /* 0x000000c0: Z0q1.0...U....Ti */
     234    0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, /* 0x000000d0: mestamp Signing  */
     235    0x32, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, 0x44, 0x65, 0x76, 0x31, /* 0x000000e0: 21.0...U....Dev1 */
     236    0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, /* 0x000000f0: .0...U....Test C */
     237    0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, /* 0x00000100: ompany1.0...U... */
     238    0x09, 0x53, 0x74, 0x75, 0x74, 0x74, 0x67, 0x61, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, /* 0x00000110: .Stuttgart1.0... */
     239    0x55, 0x04, 0x08, 0x0c, 0x02, 0x42, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, /* 0x00000120: U....BB1.0...U.. */
     240    0x13, 0x02, 0x44, 0x45, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, /* 0x00000130: ..DE0.."0...*.H. */
     241    0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, /* 0x00000140: ............0... */
     242    0x02, 0x82, 0x01, 0x01, 0x00, 0xdb, 0x18, 0x63, 0x33, 0xf2, 0x08, 0x90, 0x5a, 0xab, 0xda, 0x88, /* 0x00000150: .......c3...Z... */
     243    0x73, 0x86, 0x49, 0xea, 0x8b, 0xaf, 0xcf, 0x67, 0x15, 0xa5, 0x39, 0xe6, 0xa2, 0x94, 0x0c, 0x3f, /* 0x00000160: s.I....g..9....? */
     244    0xa1, 0x2e, 0x6c, 0xd2, 0xdf, 0x01, 0x65, 0x6d, 0xed, 0x6c, 0x4c, 0xac, 0xe7, 0x77, 0x7a, 0x45, /* 0x00000170: ..l...em.lL..wzE */
     245    0x05, 0x6b, 0x24, 0xf3, 0xaf, 0x45, 0x35, 0x6e, 0x64, 0x0a, 0xac, 0x1d, 0x37, 0xe1, 0x33, 0xa4, /* 0x00000180: .k$..E5nd...7.3. */
     246    0x92, 0xec, 0x45, 0xe8, 0x99, 0xc1, 0xde, 0x6f, 0xab, 0x7c, 0xf0, 0xdc, 0xe2, 0xc5, 0x42, 0xa3, /* 0x00000190: ..E....o.|....B. */
     247    0xea, 0xf5, 0x8a, 0xf9, 0x0e, 0xe7, 0xb3, 0x35, 0xa2, 0x75, 0x5e, 0x87, 0xd2, 0x2a, 0xd1, 0x27, /* 0x000001a0: .......5.u^..*.' */
     248    0xa6, 0x79, 0x9e, 0xfe, 0x90, 0xbf, 0x97, 0xa4, 0xa1, 0xd8, 0xf7, 0xd7, 0x05, 0x59, 0x44, 0x27, /* 0x000001b0: .y...........YD' */
     249    0x39, 0x6e, 0x33, 0x01, 0x2e, 0x46, 0x92, 0x47, 0xbe, 0x50, 0x91, 0x26, 0x27, 0xe5, 0x4b, 0x3a, /* 0x000001c0: 9n3..F.G.P.&'.K: */
     250    0x76, 0x26, 0x64, 0x92, 0x0c, 0xa0, 0x54, 0x43, 0x6f, 0x56, 0xcc, 0x7b, 0xd0, 0xe3, 0xd8, 0x39, /* 0x000001d0: v&d...TCoV.{...9 */
     251    0x5f, 0xb9, 0x41, 0xda, 0x1c, 0x62, 0x88, 0x0c, 0x45, 0x03, 0x63, 0xf8, 0xff, 0xe5, 0x3e, 0x87, /* 0x000001e0: _.A..b..E.c...>. */
     252    0x0c, 0x75, 0xc9, 0xdd, 0xa2, 0xc0, 0x1b, 0x63, 0x19, 0xeb, 0x09, 0x9d, 0xa1, 0xbb, 0x0f, 0x63, /* 0x000001f0: .u.....c.......c */
     253    0x67, 0x1c, 0xa3, 0xfd, 0x2f, 0xd1, 0x2a, 0xda, 0xd8, 0x93, 0x66, 0x45, 0x54, 0xef, 0x8b, 0x6d, /* 0x00000200: g.....*...fET..m */
     254    0x12, 0x15, 0x0f, 0xd4, 0xb5, 0x04, 0x17, 0x30, 0x5b, 0xfa, 0x12, 0x96, 0x48, 0x5b, 0x38, 0x65, /* 0x00000210: .......0[...H[8e */
     255    0xfd, 0x8f, 0x0c, 0xa3, 0x11, 0x46, 0x49, 0xe0, 0x62, 0xc3, 0xcc, 0x34, 0xe6, 0xfb, 0xab, 0x51, /* 0x00000220: .....FI.b..4...Q */
     256    0xc3, 0xd4, 0x0b, 0xdc, 0x39, 0x93, 0x87, 0x90, 0x10, 0x9f, 0xce, 0x43, 0x27, 0x31, 0xd5, 0x4e, /* 0x00000230: ....9......C'1.N */
     257    0x52, 0x60, 0xf1, 0x93, 0xd5, 0x06, 0xc4, 0x4e, 0x65, 0xb6, 0x35, 0x4a, 0x64, 0x15, 0xf8, 0xaf, /* 0x00000240: R`.....Ne.5Jd... */
     258    0x71, 0xb2, 0x42, 0x50, 0x89, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x46, 0x30, 0x44, 0x30, 0x0e, /* 0x00000250: q.BP.......F0D0. */
     259    0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x13, /* 0x00000260: ..U...........0. */
     260    0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, /* 0x00000270: ..U.%..0...+.... */
     261    0x07, 0x03, 0x08, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x52, 0x9d, /* 0x00000280: ...0...U......R. */
     262    0x4d, 0xcd, 0x41, 0xe1, 0xd2, 0x68, 0x22, 0xd3, 0x10, 0x33, 0x01, 0xca, 0xff, 0x00, 0x1d, 0x27, /* 0x00000290: M.A..h"..3.....' */
     263    0xa4, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, /* 0x000002a0: ..0...*.H....... */
     264    0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xc5, 0x5a, 0x51, 0x83, 0x68, 0x3f, 0x06, 0x39, 0x79, 0x13, /* 0x000002b0: .......ZQ.h?.9y. */
     265    0xa6, 0xf0, 0x1a, 0xf9, 0x29, 0x16, 0x2d, 0xa2, 0x07, 0xaa, 0x9b, 0xc3, 0x13, 0x88, 0x39, 0x69, /* 0x000002c0: ....).-.......9i */
     266    0xba, 0xf7, 0x0d, 0xfb, 0xc0, 0x6e, 0x3a, 0x0b, 0x49, 0x10, 0xd1, 0xbe, 0x36, 0x91, 0x3f, 0x9d, /* 0x000002d0: .....n:.I...6.?. */
     267    0xa1, 0xe8, 0xc4, 0x91, 0xf9, 0x02, 0xe1, 0xf1, 0x01, 0x15, 0x09, 0xb7, 0xa1, 0xf1, 0xec, 0x43, /* 0x000002e0: ...............C */
     268    0x0d, 0x73, 0xd1, 0x31, 0x02, 0x4a, 0xce, 0x21, 0xf2, 0xa7, 0x99, 0x7c, 0xee, 0x85, 0x54, 0xc0, /* 0x000002f0: .s.1.J.!...|..T. */
     269    0x55, 0x9b, 0x19, 0x37, 0xe8, 0xcf, 0x94, 0x41, 0x10, 0x6e, 0x67, 0xdd, 0x86, 0xaf, 0xb7, 0xfe, /* 0x00000300: U..7...A.ng..... */
     270    0x50, 0x05, 0xf6, 0xfb, 0x0a, 0xdf, 0x88, 0xb5, 0x59, 0x69, 0x98, 0x27, 0xf8, 0x81, 0x6a, 0x4a, /* 0x00000310: P.......Yi.'..jJ */
     271    0x7c, 0xf3, 0x63, 0xa9, 0x41, 0x78, 0x76, 0x12, 0xdb, 0x0e, 0x94, 0x0a, 0xdb, 0x1d, 0x3c, 0x87, /* 0x00000320: |.c.Axv.......<. */
     272    0x35, 0xca, 0x28, 0xeb, 0xb0, 0x62, 0x27, 0x69, 0xe2, 0xf3, 0x84, 0x48, 0xa2, 0x2d, 0xd7, 0x0e, /* 0x00000330: 5.(..b'i...H.-.. */
     273    0x4b, 0x6d, 0x39, 0xa7, 0x3e, 0x04, 0x94, 0x8e, 0xb6, 0x4b, 0x91, 0x01, 0x68, 0xf9, 0xd2, 0x75, /* 0x00000340: Km9.>....K..h..u */
     274    0x1b, 0xac, 0x42, 0x3b, 0x85, 0xfc, 0x5b, 0x48, 0x3a, 0x13, 0xe7, 0x1c, 0x17, 0xcd, 0x84, 0x89, /* 0x00000350: ..B;..[H:....... */
     275    0x9e, 0x5f, 0xe3, 0x77, 0xc0, 0xae, 0x34, 0xc3, 0x87, 0x76, 0x4a, 0x23, 0x30, 0xa0, 0xe1, 0x45, /* 0x00000360: ._.w..4..vJ#0..E */
     276    0x94, 0x2a, 0x5b, 0x6b, 0x5a, 0xf0, 0x1a, 0x7e, 0xa6, 0xc4, 0xed, 0xe4, 0xac, 0x5d, 0xdf, 0x87, /* 0x00000370: .*[kZ..~.....].. */
     277    0x8f, 0xc5, 0xb4, 0x8c, 0xbc, 0x70, 0xc1, 0xf7, 0xb2, 0x72, 0xbd, 0x73, 0xc9, 0x4e, 0xed, 0x8d, /* 0x00000380: .....p...r.s.N.. */
     278    0x29, 0x33, 0xe9, 0x14, 0xc1, 0x5e, 0xff, 0x39, 0xa8, 0xe7, 0x9a, 0x3b, 0x7a, 0x3c, 0xce, 0x5d, /* 0x00000390: )3...^.9...;z<.] */
     279    0x0f, 0x3c, 0x82, 0x90, 0xff, 0x81, 0x82, 0x00, 0x82, 0x5f, 0xba, 0x08, 0x79, 0xb1, 0x97, 0xc3, /* 0x000003a0: .<......._..y... */
     280    0x09, 0x75, 0xc0, 0x04, 0x9b, 0x67,                                                             /* 0x000003b0: .u...g           */
     281};
     282
     283const unsigned char g_abFakeRsaKey[] =
     284{
     285    0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xdb, 0x18, 0x63, 0x33, /* 0x00000000: 0.............c3 */
     286    0xf2, 0x08, 0x90, 0x5a, 0xab, 0xda, 0x88, 0x73, 0x86, 0x49, 0xea, 0x8b, 0xaf, 0xcf, 0x67, 0x15, /* 0x00000010: ...Z...s.I....g. */
     287    0xa5, 0x39, 0xe6, 0xa2, 0x94, 0x0c, 0x3f, 0xa1, 0x2e, 0x6c, 0xd2, 0xdf, 0x01, 0x65, 0x6d, 0xed, /* 0x00000020: .9....?..l...em. */
     288    0x6c, 0x4c, 0xac, 0xe7, 0x77, 0x7a, 0x45, 0x05, 0x6b, 0x24, 0xf3, 0xaf, 0x45, 0x35, 0x6e, 0x64, /* 0x00000030: lL..wzE.k$..E5nd */
     289    0x0a, 0xac, 0x1d, 0x37, 0xe1, 0x33, 0xa4, 0x92, 0xec, 0x45, 0xe8, 0x99, 0xc1, 0xde, 0x6f, 0xab, /* 0x00000040: ...7.3...E....o. */
     290    0x7c, 0xf0, 0xdc, 0xe2, 0xc5, 0x42, 0xa3, 0xea, 0xf5, 0x8a, 0xf9, 0x0e, 0xe7, 0xb3, 0x35, 0xa2, /* 0x00000050: |....B........5. */
     291    0x75, 0x5e, 0x87, 0xd2, 0x2a, 0xd1, 0x27, 0xa6, 0x79, 0x9e, 0xfe, 0x90, 0xbf, 0x97, 0xa4, 0xa1, /* 0x00000060: u^..*.'.y....... */
     292    0xd8, 0xf7, 0xd7, 0x05, 0x59, 0x44, 0x27, 0x39, 0x6e, 0x33, 0x01, 0x2e, 0x46, 0x92, 0x47, 0xbe, /* 0x00000070: ....YD'9n3..F.G. */
     293    0x50, 0x91, 0x26, 0x27, 0xe5, 0x4b, 0x3a, 0x76, 0x26, 0x64, 0x92, 0x0c, 0xa0, 0x54, 0x43, 0x6f, /* 0x00000080: P.&'.K:v&d...TCo */
     294    0x56, 0xcc, 0x7b, 0xd0, 0xe3, 0xd8, 0x39, 0x5f, 0xb9, 0x41, 0xda, 0x1c, 0x62, 0x88, 0x0c, 0x45, /* 0x00000090: V.{...9_.A..b..E */
     295    0x03, 0x63, 0xf8, 0xff, 0xe5, 0x3e, 0x87, 0x0c, 0x75, 0xc9, 0xdd, 0xa2, 0xc0, 0x1b, 0x63, 0x19, /* 0x000000a0: .c...>..u.....c. */
     296    0xeb, 0x09, 0x9d, 0xa1, 0xbb, 0x0f, 0x63, 0x67, 0x1c, 0xa3, 0xfd, 0x2f, 0xd1, 0x2a, 0xda, 0xd8, /* 0x000000b0: ......cg.....*.. */
     297    0x93, 0x66, 0x45, 0x54, 0xef, 0x8b, 0x6d, 0x12, 0x15, 0x0f, 0xd4, 0xb5, 0x04, 0x17, 0x30, 0x5b, /* 0x000000c0: .fET..m.......0[ */
     298    0xfa, 0x12, 0x96, 0x48, 0x5b, 0x38, 0x65, 0xfd, 0x8f, 0x0c, 0xa3, 0x11, 0x46, 0x49, 0xe0, 0x62, /* 0x000000d0: ...H[8e.....FI.b */
     299    0xc3, 0xcc, 0x34, 0xe6, 0xfb, 0xab, 0x51, 0xc3, 0xd4, 0x0b, 0xdc, 0x39, 0x93, 0x87, 0x90, 0x10, /* 0x000000e0: ..4...Q....9.... */
     300    0x9f, 0xce, 0x43, 0x27, 0x31, 0xd5, 0x4e, 0x52, 0x60, 0xf1, 0x93, 0xd5, 0x06, 0xc4, 0x4e, 0x65, /* 0x000000f0: ..C'1.NR`.....Ne */
     301    0xb6, 0x35, 0x4a, 0x64, 0x15, 0xf8, 0xaf, 0x71, 0xb2, 0x42, 0x50, 0x89, 0x02, 0x03, 0x01, 0x00, /* 0x00000100: .5Jd...q.BP..... */
     302    0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd0, 0x5e, 0x09, 0x3a, 0xc5, 0xdc, 0xcf, 0x2c, 0xec, 0x74, /* 0x00000110: .......^.:...,.t */
     303    0x11, 0x81, 0x8d, 0x1d, 0x8f, 0x2a, 0xfa, 0x31, 0x4d, 0xe0, 0x90, 0x1a, 0xd8, 0xf5, 0x95, 0xc7, /* 0x00000120: .....*.1M....... */
     304    0x70, 0x5c, 0x62, 0x42, 0xac, 0xe9, 0xd9, 0xf2, 0x14, 0xf1, 0xd0, 0x25, 0xbb, 0xeb, 0x06, 0xfe, /* 0x00000130: p\bB.......%.... */
     305    0x09, 0xd6, 0x75, 0x67, 0xd7, 0x39, 0xc1, 0xa0, 0x67, 0x34, 0x4d, 0xd2, 0x12, 0x97, 0xaa, 0x5d, /* 0x00000140: ..ug.9..g4M....] */
     306    0xeb, 0x0e, 0xb0, 0x16, 0x6c, 0x78, 0x8e, 0xa0, 0x75, 0xa3, 0xaa, 0x57, 0x88, 0x3b, 0x43, 0x4f, /* 0x00000150: ....lx..u..W.;CO */
     307    0x75, 0x85, 0x67, 0xb0, 0x9b, 0xdd, 0x49, 0x0e, 0x6e, 0xdb, 0xea, 0xb3, 0xd4, 0x88, 0x54, 0xa0, /* 0x00000160: u.g...I.n.....T. */
     308    0x46, 0x0d, 0x55, 0x6d, 0x98, 0xbd, 0x20, 0xf9, 0x9f, 0x61, 0x2d, 0x6f, 0xc7, 0xd7, 0x16, 0x66, /* 0x00000170: F.Um.. ..a-o...f */
     309    0x72, 0xc7, 0x73, 0xbe, 0x9e, 0x48, 0xdc, 0x65, 0x12, 0x46, 0x35, 0x69, 0x55, 0xd8, 0x6b, 0x81, /* 0x00000180: r.s..H.e.F5iU.k. */
     310    0x78, 0x40, 0x15, 0x93, 0x60, 0x31, 0x4e, 0x87, 0x15, 0x2a, 0x74, 0x74, 0x7b, 0xa0, 0x1f, 0x59, /* 0x00000190: x@..`1N..*tt{..Y */
     311    0x8d, 0xc8, 0x3f, 0xdd, 0xf0, 0x13, 0x88, 0x2a, 0x4a, 0xf2, 0xf5, 0xf1, 0x9e, 0xf3, 0x2d, 0x9c, /* 0x000001a0: ..?....*J.....-. */
     312    0x8e, 0xbc, 0xb1, 0x21, 0x45, 0xc7, 0x44, 0x0c, 0x6a, 0xfe, 0x4c, 0x20, 0xdc, 0x73, 0xda, 0x62, /* 0x000001b0: ...!E.D.j.L .s.b */
     313    0x21, 0xcb, 0xdf, 0x06, 0xfc, 0x90, 0xc2, 0xbd, 0xd6, 0xde, 0xfb, 0xf6, 0x08, 0x69, 0x5d, 0xea, /* 0x000001c0: !............i]. */
     314    0xb3, 0x7f, 0x93, 0x61, 0xf2, 0xc1, 0xd0, 0x61, 0x4f, 0xd5, 0x5b, 0x63, 0xba, 0xb0, 0x3b, 0x07, /* 0x000001d0: ...a...aO.[c..;. */
     315    0x7a, 0x55, 0xcd, 0xa1, 0xae, 0x8a, 0x92, 0x21, 0xcc, 0x2f, 0x5b, 0xf8, 0x40, 0x6a, 0xcd, 0xd5, /* 0x000001e0: zU.....!..[.@j.. */
     316    0x5f, 0x15, 0xf4, 0xb6, 0xbd, 0xe5, 0x91, 0xb9, 0xa8, 0xcc, 0x2a, 0xa8, 0xa6, 0x67, 0x57, 0x2b, /* 0x000001f0: _.........*..gW+ */
     317    0x4b, 0xe9, 0x88, 0xe0, 0xbb, 0x58, 0xac, 0x69, 0x5f, 0x3c, 0x76, 0x28, 0xa6, 0x9d, 0xbc, 0x71, /* 0x00000200: K....X.i_<v(...q */
     318    0x7f, 0xcb, 0x0c, 0xc0, 0xbd, 0x61, 0x02, 0x81, 0x81, 0x00, 0xfc, 0x62, 0x79, 0x5b, 0xac, 0xf6, /* 0x00000210: .....a.....by[.. */
     319    0x9b, 0x8c, 0xaa, 0x76, 0x2a, 0x30, 0x0e, 0xcf, 0x6b, 0x88, 0x72, 0x54, 0x8c, 0xdf, 0xf3, 0x9d, /* 0x00000220: ...v*0..k.rT.... */
     320    0x84, 0xbb, 0xe7, 0x9d, 0xd4, 0x04, 0x29, 0x3c, 0xb5, 0x9d, 0x60, 0x9a, 0xcc, 0x12, 0xf3, 0xfa, /* 0x00000230: ......)<..`..... */
     321    0x64, 0x30, 0x23, 0x47, 0xc6, 0xa4, 0x8b, 0x6c, 0x73, 0x6c, 0x6b, 0x78, 0x82, 0xec, 0x05, 0x19, /* 0x00000240: d0#G...lslkx.... */
     322    0xde, 0xdd, 0xde, 0x52, 0xc5, 0x20, 0xd1, 0x11, 0x58, 0x19, 0x07, 0x5a, 0x90, 0xdd, 0x22, 0x91, /* 0x00000250: ...R. ..X..Z..". */
     323    0x89, 0x22, 0x3f, 0x12, 0x54, 0x1a, 0xb8, 0x79, 0xd8, 0x6c, 0xbc, 0xf5, 0x0d, 0xc7, 0x73, 0x5c, /* 0x00000260: ."?.T..y.l....s\ */
     324    0xed, 0xba, 0x40, 0x2b, 0x72, 0x34, 0x34, 0x97, 0xfa, 0x49, 0xf6, 0x43, 0x7c, 0xbc, 0x61, 0x30, /* 0x00000270: ..@+r44..I.C|.a0 */
     325    0x54, 0x22, 0x21, 0x5f, 0x77, 0x68, 0x6b, 0x83, 0x95, 0xc6, 0x8d, 0xb8, 0x25, 0x3a, 0xd3, 0xb2, /* 0x00000280: T"!_whk.....%:.. */
     326    0xbe, 0x29, 0x94, 0x01, 0x15, 0xf0, 0x36, 0x9d, 0x3e, 0xff, 0x02, 0x81, 0x81, 0x00, 0xde, 0x3b, /* 0x00000290: .)....6.>......; */
     327    0xd6, 0x4b, 0x38, 0x69, 0x9b, 0x71, 0x29, 0x89, 0xd4, 0x6d, 0x8c, 0x41, 0xee, 0xe2, 0x4d, 0xfc, /* 0x000002a0: .K8i.q)..m.A..M. */
     328    0xf0, 0x9a, 0x73, 0xf1, 0x15, 0x94, 0xac, 0x1b, 0x68, 0x5f, 0x79, 0x15, 0x3a, 0x41, 0x55, 0x09, /* 0x000002b0: ..s.....h_y.:AU. */
     329    0xc7, 0x1e, 0xec, 0x27, 0x67, 0xe2, 0xdc, 0x54, 0xa8, 0x09, 0xe6, 0x46, 0x92, 0x92, 0x03, 0x8d, /* 0x000002c0: ...'g..T...F.... */
     330    0xe5, 0x96, 0xfb, 0x1a, 0xdd, 0x59, 0x6f, 0x92, 0xf1, 0xf6, 0x8f, 0x76, 0xb0, 0xc5, 0xe6, 0xd7, /* 0x000002d0: .....Yo....v.... */
     331    0x1b, 0x25, 0xaf, 0x04, 0x9f, 0xd8, 0x71, 0x27, 0x97, 0x99, 0x23, 0x09, 0x7d, 0xef, 0x06, 0x13, /* 0x000002e0: .%....q'..#.}... */
     332    0xab, 0xdc, 0xa2, 0xd8, 0x5f, 0xc5, 0xec, 0xf3, 0x62, 0x20, 0x72, 0x7b, 0xa8, 0xc7, 0x09, 0x24, /* 0x000002f0: ...._...b r{...$ */
     333    0xaf, 0x72, 0xc9, 0xea, 0xb8, 0x2d, 0xda, 0x00, 0xc8, 0xfe, 0xb4, 0x9f, 0x9f, 0xc7, 0xa9, 0xf7, /* 0x00000300: .r...-.......... */
     334    0x1d, 0xce, 0xb1, 0xdb, 0xc5, 0x8a, 0x4e, 0xe8, 0x88, 0x77, 0x68, 0xdd, 0xf8, 0x77, 0x02, 0x81, /* 0x00000310: ......N..wh..w.. */
     335    0x80, 0x5b, 0xa5, 0x8e, 0x98, 0x01, 0xa8, 0xd3, 0x37, 0x33, 0x37, 0x11, 0x7e, 0xbe, 0x02, 0x07, /* 0x00000320: .[......737.~... */
     336    0xf4, 0x56, 0x3f, 0xe9, 0x9f, 0xf1, 0x20, 0xc3, 0xf0, 0x4f, 0xdc, 0xf9, 0xfe, 0x40, 0xd3, 0x30, /* 0x00000330: .V?... [email protected] */
     337    0xc7, 0xe3, 0x2a, 0x92, 0xec, 0x56, 0xf8, 0x17, 0xa5, 0x7b, 0x4a, 0x37, 0x11, 0xcd, 0x27, 0x26, /* 0x00000340: ..*..V...{J7..'& */
     338    0x8a, 0xba, 0x43, 0xda, 0x96, 0xc6, 0x0b, 0x6c, 0xe8, 0x78, 0x30, 0xea, 0x30, 0x4e, 0x7a, 0xd3, /* 0x00000350: ..C....l.x0.0Nz. */
     339    0xd8, 0xd2, 0xd8, 0xca, 0x3d, 0xe2, 0xad, 0xa2, 0x74, 0x73, 0x1e, 0xbe, 0xb7, 0xad, 0x41, 0x61, /* 0x00000360: ....=...ts....Aa */
     340    0x9b, 0xaa, 0xc9, 0xf9, 0xa4, 0xf1, 0x79, 0x4f, 0x42, 0x10, 0xc7, 0x36, 0x03, 0x4b, 0x0d, 0xdc, /* 0x00000370: ......yOB..6.K.. */
     341    0xef, 0x3a, 0xa3, 0xab, 0x09, 0xe4, 0xe8, 0xdd, 0xc4, 0x3f, 0x06, 0x21, 0xa0, 0x23, 0x5a, 0x76, /* 0x00000380: .:.......?.!.#Zv */
     342    0xea, 0xd0, 0xcf, 0x8b, 0x85, 0x5f, 0x16, 0x4b, 0x03, 0x62, 0x21, 0x3a, 0xcc, 0x2d, 0xa8, 0xd0, /* 0x00000390: ....._.K.b!:.-.. */
     343    0x15, 0x02, 0x81, 0x80, 0x51, 0xf6, 0x89, 0xbb, 0xa6, 0x6b, 0xb4, 0xcb, 0xd0, 0xc1, 0x27, 0xda, /* 0x000003a0: ....Q....k....'. */
     344    0xdb, 0x6e, 0xf9, 0xd6, 0xf7, 0x62, 0x81, 0xae, 0xc5, 0x72, 0x36, 0x3e, 0x66, 0x17, 0x99, 0xb0, /* 0x000003b0: .n...b...r6>f... */
     345    0x14, 0xad, 0x52, 0x96, 0x03, 0xf2, 0x1e, 0x41, 0x76, 0x61, 0xb6, 0x3c, 0x02, 0x7d, 0x2a, 0x98, /* 0x000003c0: ..R....Ava.<.}*. */
     346    0xb4, 0x18, 0x75, 0x38, 0x6b, 0x1d, 0x2b, 0x7f, 0x3a, 0xcf, 0x96, 0xb1, 0xc4, 0xa7, 0xd2, 0x9b, /* 0x000003d0: ..u8k.+.:....... */
     347    0xd8, 0x1f, 0xb3, 0x64, 0xda, 0x15, 0x9d, 0xca, 0x91, 0x39, 0x48, 0x67, 0x00, 0x9c, 0xd4, 0x99, /* 0x000003e0: ...d.....9Hg.... */
     348    0xc3, 0x45, 0x5d, 0xf0, 0x09, 0x32, 0xba, 0x21, 0x1e, 0xe2, 0x64, 0xb8, 0x50, 0x03, 0x17, 0xbe, /* 0x000003f0: .E]..2.!..d.P... */
     349    0xd5, 0xda, 0x6b, 0xce, 0x34, 0xbe, 0x16, 0x03, 0x65, 0x1b, 0x2f, 0xa0, 0xa1, 0x95, 0xc6, 0x8b, /* 0x00000400: ..k.4...e....... */
     350    0xc2, 0x3c, 0x59, 0x26, 0xbf, 0xb6, 0x07, 0x85, 0x53, 0x2d, 0xb6, 0x36, 0xa3, 0x91, 0xb9, 0xbb, /* 0x00000410: .<Y&....S-.6.... */
     351    0x28, 0xaf, 0x2d, 0x53, 0x02, 0x81, 0x81, 0x00, 0xd7, 0xbc, 0x70, 0xd8, 0x18, 0x4f, 0x65, 0x8c, /* 0x00000420: (.-S......p..Oe. */
     352    0x68, 0xca, 0x35, 0x77, 0x43, 0x50, 0x9b, 0xa1, 0xa3, 0x9a, 0x0e, 0x2d, 0x7b, 0x38, 0xf8, 0xba, /* 0x00000430: h.5wCP.....-{8.. */
     353    0x14, 0x91, 0x3b, 0xc3, 0x3b, 0x1b, 0xa0, 0x6d, 0x45, 0xe4, 0xa8, 0x28, 0x97, 0xf6, 0x89, 0x13, /* 0x00000440: ..;.;..mE..(.... */
     354    0xb6, 0x16, 0x6d, 0x65, 0x47, 0x8c, 0xa6, 0x21, 0xf8, 0x6a, 0xce, 0x4e, 0x44, 0x5e, 0x81, 0x47, /* 0x00000450: ..meG..!.j.ND^.G */
     355    0xd9, 0xad, 0x8a, 0xb9, 0xd9, 0xe9, 0x3e, 0x33, 0x1e, 0x5f, 0xe9, 0xe9, 0xa7, 0xea, 0x60, 0x75, /* 0x00000460: ......>3._....`u */
     356    0x02, 0x57, 0x71, 0xb5, 0xed, 0x47, 0x77, 0xda, 0x1a, 0x40, 0x38, 0xab, 0x82, 0xd2, 0x0d, 0xf5, /* 0x00000470: .Wq..Gw..@8..... */
     357    0x0e, 0x8e, 0xa9, 0x24, 0xdc, 0x30, 0xc9, 0x98, 0xa2, 0x05, 0xcd, 0xca, 0x01, 0xcf, 0xae, 0x1d, /* 0x00000480: ...$.0.......... */
     358    0xe9, 0x02, 0x47, 0x0e, 0x46, 0x1d, 0x52, 0x02, 0x9a, 0x99, 0x22, 0x23, 0x7f, 0xf8, 0x9e, 0xc2, /* 0x00000490: ..G.F.R..."#.... */
     359    0x16, 0x86, 0xca, 0xa0, 0xa7, 0x34, 0xfb, 0xbc,                                                 /* 0x000004a0: .....4..         */
     360};
     361
     362
     363/**
     364 * Certificate w/ public key + private key pair for signing.
     365 */
     366class SignToolKeyPair
     367{
     368protected:
     369    /* Context: */
     370    const char             *m_pszWhat;
     371    bool                    m_fMandatory;
     372
     373    /* Parameters kept till finalizing parsing: */
     374    const char             *m_pszCertFile;
     375    const char             *m_pszCertSha1;
     376    uint8_t                 m_abCertSha1[RTSHA1_HASH_SIZE];
     377    const char             *m_pszCertSubject;
     378    const char             *m_pszCertStore;
     379    bool                    m_fMachineStore; /**< false = personal store */
     380
     381    const char             *m_pszKeyFile;
     382    const char             *m_pszKeyPassword;
     383    const char             *m_pszKeyName;
     384    const char             *m_pszKeyProvider;
     385
     386    /** String buffer for m_pszKeyPassword when read from file. */
     387    RTCString               m_strPassword;
     388    /** Storage for pCertificate when it's loaded from a file. */
     389    RTCRX509CERTIFICATE     m_DecodedCert;
     390#ifdef RT_OS_WINDOWS
     391    /** For the fake certificate */
     392    RTCRX509CERTIFICATE     m_DecodedFakeCert;
     393    /** The certificate store. */
     394    HCERTSTORE              m_hStore;
     395    /** The windows certificate context. */
     396    PCCERT_CONTEXT          m_pCertCtx;
     397    /** Whether hNCryptPrivateKey/hLegacyPrivateKey needs freeing or not. */
     398    BOOL                    m_fFreePrivateHandle;
     399#endif
     400
     401    /** Set if already finalized. */
     402    bool                    m_fFinalized;
     403
     404public: /* used to be a struct, thus not prefix either. */
     405    /* Result: */
     406    PCRTCRX509CERTIFICATE   pCertificate;
     407    RTCRKEY                 hPrivateKey;
     408#ifdef RT_OS_WINDOWS
     409    PCRTCRX509CERTIFICATE   pCertificateReal;
     410    NCRYPT_KEY_HANDLE       hNCryptPrivateKey;
     411    HCRYPTPROV              hLegacyPrivateKey;
     412#endif
     413
     414public:
     415    SignToolKeyPair(const char *a_pszWhat, bool a_fMandatory = false)
     416        : m_pszWhat(a_pszWhat)
     417        , m_fMandatory(a_fMandatory)
     418        , m_pszCertFile(NULL)
     419        , m_pszCertSha1(NULL)
     420        , m_pszCertSubject(NULL)
     421        , m_pszCertStore("MY")
     422        , m_fMachineStore(false)
     423        , m_pszKeyFile(NULL)
     424        , m_pszKeyPassword(NULL)
     425        , m_pszKeyName(NULL)
     426        , m_pszKeyProvider(NULL)
     427#ifdef RT_OS_WINDOWS
     428        , m_hStore(NULL)
     429        , m_pCertCtx(NULL)
     430        , m_fFreePrivateHandle(FALSE)
     431#endif
     432        , m_fFinalized(false)
     433        , pCertificate(NULL)
     434        , hPrivateKey(NIL_RTCRKEY)
     435#ifdef RT_OS_WINDOWS
     436        , pCertificateReal(NULL)
     437        , hNCryptPrivateKey(0)
     438        , hLegacyPrivateKey(0)
     439#endif
     440    {
     441        RT_ZERO(m_DecodedCert);
     442#ifdef RT_OS_WINDOWS
     443        RT_ZERO(m_DecodedFakeCert);
     444#endif
     445    }
     446
     447    ~SignToolKeyPair()
     448    {
     449        if (hPrivateKey != NIL_RTCRKEY)
     450        {
     451            RTCrKeyRelease(hPrivateKey);
     452            hPrivateKey = NIL_RTCRKEY;
     453        }
     454        if (pCertificate == &m_DecodedCert)
     455        {
     456            RTCrX509Certificate_Delete(&m_DecodedCert);
     457            pCertificate = NULL;
     458        }
     459#ifdef RT_OS_WINDOWS
     460        if (pCertificate == &m_DecodedFakeCert)
     461        {
     462            RTCrX509Certificate_Delete(&m_DecodedFakeCert);
     463            RTCrX509Certificate_Delete(&m_DecodedCert);
     464            pCertificate = NULL;
     465            pCertificateReal = NULL;
     466        }
     467#endif
     468#ifdef RT_OS_WINDOWS
     469        if (m_pCertCtx != NULL)
     470        {
     471             CertFreeCertificateContext(m_pCertCtx);
     472             m_pCertCtx = NULL;
     473        }
     474        if (m_hStore != NULL)
     475        {
     476            CertCloseStore(m_hStore, 0);
     477            m_hStore = NULL;
     478        }
     479#endif
     480    }
     481
     482    bool isComplete(void) const
     483    {
     484        return pCertificate && hPrivateKey != NIL_RTCRKEY;
     485    }
     486
     487    bool isNull(void) const
     488    {
     489        return pCertificate == NULL && hPrivateKey == NIL_RTCRKEY;
     490    }
     491
     492    RTEXITCODE handleOption(unsigned offOpt, PRTGETOPTUNION pValueUnion)
     493    {
     494        AssertReturn(!m_fFinalized, RTMsgErrorExitFailure("Cannot handle options after finalizeOptions was called!"));
     495        switch (offOpt)
     496        {
     497            case OPT_OFF_CERT_FILE:
     498                m_pszCertFile    = pValueUnion->psz;
     499                m_pszCertSha1    = NULL;
     500                m_pszCertSubject = NULL;
     501                break;
     502            case OPT_OFF_CERT_SHA1:
     503            {
     504                /* Crude normalization of input separators to colons, since it's likely
     505                   to use spaces and our conversion function only does colons or nothing. */
     506                char szDigest[RTSHA1_DIGEST_LEN * 3 + 1];
     507                int rc = RTStrCopy(szDigest, sizeof(szDigest), pValueUnion->psz);
     508                if (RT_SUCCESS(rc))
     509                {
     510                    char  *pszDigest = RTStrStrip(szDigest);
     511                    size_t offDst    = 0;
     512                    size_t offSrc    = 0;
     513                    char   ch;
     514                    while ((ch = pszDigest[offSrc++]) != '\0')
     515                    {
     516                        if (ch == ' ' || ch == '\t' || ch == ':')
     517                        {
     518                            while ((ch = pszDigest[offSrc]) == ' ' || ch == '\t' || ch == ':')
     519                                offSrc++;
     520                            ch = ch ? ':' : '\0';
     521                        }
     522                        pszDigest[offDst++] = ch;
     523                    }
     524                    pszDigest[offDst] = '\0';
     525
     526                    /** @todo add a more relaxed input mode to RTStrConvertHexBytes that can deal
     527                     *        with spaces as well as multi-byte cluster of inputs. */
     528                    rc = RTStrConvertHexBytes(pszDigest, m_abCertSha1, RTSHA1_HASH_SIZE, RTSTRCONVERTHEXBYTES_F_SEP_COLON);
     529                    if (RT_SUCCESS(rc))
     530                    {
     531                        m_pszCertFile    = NULL;
     532                        m_pszCertSha1    = pValueUnion->psz;
     533                        m_pszCertSubject = NULL;
     534                        break;
     535                    }
     536                }
     537                return RTMsgErrorExitFailure("malformed SHA-1 certificate fingerprint (%Rrc): %s", rc, pValueUnion->psz);
     538            }
     539            case OPT_OFF_CERT_SUBJECT:
     540                m_pszCertFile    = NULL;
     541                m_pszCertSha1    = NULL;
     542                m_pszCertSubject = pValueUnion->psz;
     543                break;
     544            case OPT_OFF_CERT_STORE:
     545                m_pszCertStore   = pValueUnion->psz;
     546                break;
     547            case OPT_OFF_CERT_STORE_MACHINE:
     548                m_fMachineStore  = true;
     549                break;
     550
     551            case OPT_OFF_KEY_FILE:
     552                m_pszKeyFile     = pValueUnion->psz;
     553                m_pszKeyName     = NULL;
     554                break;
     555            case OPT_OFF_KEY_NAME:
     556                m_pszKeyFile     = NULL;
     557                m_pszKeyName     = pValueUnion->psz;
     558                break;
     559            case OPT_OFF_KEY_PROVIDER:
     560                m_pszKeyProvider = pValueUnion->psz;
     561                break;
     562            case OPT_OFF_KEY_PASSWORD:
     563                m_pszKeyPassword = pValueUnion->psz;
     564                break;
     565            case OPT_OFF_KEY_PASSWORD_FILE:
     566            {
     567                m_pszKeyPassword = NULL;
     568
     569                size_t const cchMax = 512;
     570                int rc = m_strPassword.reserveNoThrow(cchMax + 1);
     571                if (RT_FAILURE(rc))
     572                    return RTMsgErrorExitFailure("out of memory");
     573
     574                PRTSTREAM  pStrm  = g_pStdIn;
     575                bool const fClose = strcmp(pValueUnion->psz, "stdin") != 0;
     576                if (fClose)
     577                {
     578                    rc = RTStrmOpen(pValueUnion->psz, "r", &pStrm);
     579                    if (RT_FAILURE(rc))
     580                        return RTMsgErrorExitFailure("Failed to open password file '%s' for reading: %Rrc", pValueUnion->psz, rc);
     581                }
     582                rc = RTStrmGetLine(pStrm, m_strPassword.mutableRaw(), cchMax);
     583                if (fClose)
     584                    RTStrmClose(pStrm);
     585                if (rc == VERR_BUFFER_OVERFLOW || rc == VINF_BUFFER_OVERFLOW)
     586                    return RTMsgErrorExitFailure("Password from '%s' is too long (max %zu)", pValueUnion->psz, cchMax);
     587                if (RT_FAILURE(rc))
     588                    return RTMsgErrorExitFailure("Error reading password from '%s': %Rrc", pValueUnion->psz, rc);
     589
     590                m_strPassword.jolt();
     591                m_strPassword.stripRight();
     592                m_pszKeyPassword = m_strPassword.c_str();
     593                break;
     594            }
     595            default:
     596                AssertFailedReturn(RTMsgErrorExitFailure("Invalid offOpt=%u!\n", offOpt));
     597        }
     598        return RTEXITCODE_SUCCESS;
     599    }
     600
     601    RTEXITCODE finalizeOptions(unsigned cVerbosity)
     602    {
     603        RT_NOREF(cVerbosity);
     604
     605        /* Only do this once. */
     606        if (m_fFinalized)
     607            return RTEXITCODE_SUCCESS;
     608        m_fFinalized = true;
     609
     610        /*
     611         * Got a cert? Is it required?
     612         */
     613        bool const fHasKey  = (   m_pszKeyFile     != NULL
     614                               || m_pszKeyName     != NULL);
     615        bool const fHasCert = (   m_pszCertFile    != NULL
     616                               || m_pszCertSha1    != NULL
     617                               || m_pszCertSubject != NULL);
     618        if (!fHasCert)
     619        {
     620            if (m_fMandatory)
     621                return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Specifying a %s certificiate is required.", m_pszWhat);
     622            return RTEXITCODE_SUCCESS;
     623        }
     624
     625        /*
     626         * Get the certificate.
     627         */
     628        RTERRINFOSTATIC ErrInfo;
     629        /* From file: */
     630        if (m_pszCertFile)
     631        {
     632            int rc = RTCrX509Certificate_ReadFromFile(&m_DecodedCert, m_pszCertFile, 0, &g_RTAsn1DefaultAllocator,
     633                                                      RTErrInfoInitStatic(&ErrInfo));
     634            if (RT_FAILURE(rc))
     635                return RTMsgErrorExitFailure("Error reading %s certificate from '%s': %Rrc%#RTeim",
     636                                             m_pszWhat, m_pszCertFile, rc, &ErrInfo.Core);
     637            pCertificate = &m_DecodedCert;
     638        }
     639        /* From certificate store by name (substring) or fingerprint: */
     640        else
     641        {
     642#ifdef RT_OS_WINDOWS
     643            m_hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, X509_ASN_ENCODING, NULL,
     644                                     CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_STORE_READONLY_FLAG
     645                                     | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_ENUM_ARCHIVED_FLAG
     646                                     | (m_fMachineStore ? CERT_SYSTEM_STORE_LOCAL_MACHINE : CERT_SYSTEM_STORE_CURRENT_USER),
     647                                     m_pszCertStore);
     648            if (m_hStore == NULL)
     649                return RTMsgErrorExitFailure("Failed to open %s store '%s': %Rwc (%u)", m_fMachineStore ? "machine" : "user",
     650                                             m_pszCertStore, GetLastError(), GetLastError());
     651
     652            CRYPT_HASH_BLOB Thumbprint  = { RTSHA1_HASH_SIZE, m_abCertSha1 };
     653            PRTUTF16        pwszSubject = NULL;
     654            void const     *pvFindParam = &Thumbprint;
     655            DWORD           fFind       = CERT_FIND_SHA1_HASH;
     656            if (!m_pszCertSha1)
     657            {
     658                int rc = RTStrToUtf16(m_pszCertSubject, &pwszSubject);
     659                if (RT_FAILURE(rc))
     660                    return RTMsgErrorExitFailure("RTStrToUtf16 failed: %Rrc, input %.*Rhxs",
     661                                                 rc, strlen(m_pszCertSubject), m_pszCertSubject);
     662                pvFindParam = pwszSubject;
     663                fFind       = CERT_FIND_SUBJECT_STR;
     664            }
     665
     666            while ((m_pCertCtx = CertFindCertificateInStore(m_hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0 /*fFlags*/,
     667                                                           fFind, pvFindParam, m_pCertCtx)) != NULL)
     668            {
     669                if (m_pCertCtx->dwCertEncodingType & X509_ASN_ENCODING)
     670                {
     671                    RTASN1CURSORPRIMARY PrimaryCursor;
     672                    RTAsn1CursorInitPrimary(&PrimaryCursor, m_pCertCtx->pbCertEncoded, m_pCertCtx->cbCertEncoded,
     673                                            RTErrInfoInitStatic(&ErrInfo),
     674                                            &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "CurCtx");
     675                    int rc = RTCrX509Certificate_DecodeAsn1(&PrimaryCursor.Cursor, 0, &m_DecodedCert, "Cert");
     676                    if (RT_SUCCESS(rc))
     677                    {
     678                        pCertificate = &m_DecodedCert;
     679                        break;
     680                    }
     681                    RTMsgError("failed to decode certificate %p: %Rrc%#RTeim", m_pCertCtx, rc, &ErrInfo.Core);
     682                }
     683            }
     684
     685            RTUtf16Free(pwszSubject);
     686            if (!m_pCertCtx)
     687                return RTMsgErrorExitFailure("No certificate found matching %s '%s' (%Rwc / %u)",
     688                                             m_pszCertSha1 ? "thumbprint" : "subject substring",
     689                                             m_pszCertSha1 ? m_pszCertSha1 : m_pszCertSubject, GetLastError(), GetLastError());
     690
     691            /* Use this for private key too? */
     692            if (!fHasKey)
     693            {
     694                HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hTmpPrivateKey = 0;
     695                DWORD                           dwKeySpec      = 0;
     696                if (CryptAcquireCertificatePrivateKey(m_pCertCtx,
     697                                                      CRYPT_ACQUIRE_SILENT_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG
     698                                                      | CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG
     699                                                      | CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG,
     700                                                      NULL, &hTmpPrivateKey, &dwKeySpec, &m_fFreePrivateHandle))
     701                {
     702                    if (cVerbosity > 1)
     703                        RTMsgInfo("hTmpPrivateKey=%p m_fFreePrivateHandle=%d dwKeySpec=%#x",
     704                                  hTmpPrivateKey, m_fFreePrivateHandle, dwKeySpec);
     705                    Assert(dwKeySpec == CERT_NCRYPT_KEY_SPEC);
     706                    if (dwKeySpec == CERT_NCRYPT_KEY_SPEC)
     707                        hNCryptPrivateKey = hTmpPrivateKey;
     708                    else
     709                        hLegacyPrivateKey = hTmpPrivateKey;   /** @todo remove or drop CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG */
     710                    return loadFakePrivateKeyAndCert();
     711                }
     712                return RTMsgErrorExitFailure("CryptAcquireCertificatePrivateKey failed: %Rwc (%d)", GetLastError(), GetLastError());
     713            }
     714#else
     715            return RTMsgErrorExitFailure("Certificate store support is missing on this host");
     716#endif
     717        }
     718
     719        /*
     720         * Get hold of the private key (if someone above already did, they'd returned already).
     721         */
     722        Assert(hPrivateKey == NIL_RTCRKEY);
     723        /* Use cert file if nothing else specified. */
     724        if (!fHasKey && m_pszCertFile)
     725            m_pszKeyFile = m_pszCertFile;
     726
     727        /* Load from file:*/
     728        if (m_pszKeyFile)
     729        {
     730            int rc = RTCrKeyCreateFromFile(&hPrivateKey, 0 /*fFlags*/, m_pszKeyFile, m_pszKeyPassword,
     731                                           RTErrInfoInitStatic(&ErrInfo));
     732            if (RT_FAILURE(rc))
     733                return RTMsgErrorExitFailure("Error reading the %s private key from '%s': %Rrc%#RTeim",
     734                                             m_pszWhat, m_pszKeyFile, rc, &ErrInfo.Core);
     735        }
     736        /* From key store: */
     737        else
     738        {
     739            return RTMsgErrorExitFailure("Key store support is missing on this host");
     740        }
     741
     742        return RTEXITCODE_SUCCESS;
     743    }
     744
     745#ifdef RT_OS_WINDOWS
     746    RTEXITCODE loadFakePrivateKeyAndCert()
     747    {
     748        int rc = RTCrX509Certificate_ReadFromBuffer(&m_DecodedFakeCert, g_abFakeCertificate, sizeof(g_abFakeCertificate),
     749                                                    0 /*fFlags*/, &g_RTAsn1DefaultAllocator, NULL, NULL);
     750        if (RT_FAILURE(rc))
     751            return RTMsgErrorExitFailure("RTCrX509Certificate_ReadFromBuffer/g_abFakeCertificate failed: %Rrc", rc);
     752        pCertificateReal = pCertificate;
     753        pCertificate = &m_DecodedFakeCert;
     754
     755        rc = RTCrKeyCreateFromBuffer(&hPrivateKey, 0 /*fFlags*/, g_abFakeRsaKey, sizeof(g_abFakeRsaKey), NULL, NULL, NULL);
     756        if (RT_FAILURE(rc))
     757            return RTMsgErrorExitFailure("RTCrKeyCreateFromBuffer/g_abFakeRsaKey failed: %Rrc", rc);
     758        return RTEXITCODE_SUCCESS;
     759    }
     760
     761#endif
     762};
     763
     764
     765/*********************************************************************************************************************************
     766*   Workers.                                                                                                                     *
     767*********************************************************************************************************************************/
    195768
    196769
     
    12371810}
    12381811
     1812#ifdef RT_OS_WINDOWS
     1813
     1814static PCRTUTF16 GetBCryptNameFromCrDigest(RTCRDIGEST hDigest)
     1815{
     1816    switch (RTCrDigestGetType(hDigest))
     1817    {
     1818        case RTDIGESTTYPE_MD2:      return BCRYPT_MD2_ALGORITHM;
     1819        case RTDIGESTTYPE_MD4:      return BCRYPT_MD4_ALGORITHM;
     1820        case RTDIGESTTYPE_SHA1:     return BCRYPT_SHA1_ALGORITHM;
     1821        case RTDIGESTTYPE_SHA256:   return BCRYPT_SHA256_ALGORITHM;
     1822        case RTDIGESTTYPE_SHA384:   return BCRYPT_SHA384_ALGORITHM;
     1823        case RTDIGESTTYPE_SHA512:   return BCRYPT_SHA512_ALGORITHM;
     1824        default:
     1825            RTMsgError("No BCrypt translation for %s/%d!", RTCrDigestGetAlgorithmOid(hDigest), RTCrDigestGetType(hDigest));
     1826            return L"No BCrypt translation";
     1827    }
     1828}
     1829
     1830static RTEXITCODE
     1831SignToolPkcs7_Pkcs7SignStuffAgainWithReal(const char *pszWhat, SignToolKeyPair *pCertKeyPair, unsigned cVerbosity,
     1832                                          PRTCRPKCS7CONTENTINFO pContentInfo, void **ppvSigned, size_t *pcbSigned)
     1833
     1834{
     1835    RT_NOREF(cVerbosity);
     1836
     1837    /*
     1838     * First remove the fake certificate from the PKCS7 structure and insert the real one.
     1839     */
     1840    PRTCRPKCS7SIGNEDDATA pSignedData = pContentInfo->u.pSignedData;
     1841    unsigned iCert = pSignedData->Certificates.cItems;
     1842    while (iCert-- > 0)
     1843    {
     1844        PCRTCRPKCS7CERT pCert = pSignedData->Certificates.papItems[iCert];
     1845        if (   pCert->enmChoice == RTCRPKCS7CERTCHOICE_X509
     1846            && RTCrX509Certificate_MatchIssuerAndSerialNumber(pCert->u.pX509Cert,
     1847                                                              &pCertKeyPair->pCertificate->TbsCertificate.Issuer,
     1848                                                              &pCertKeyPair->pCertificate->TbsCertificate.SerialNumber))
     1849            RTCrPkcs7SetOfCerts_Erase(&pSignedData->Certificates, iCert);
     1850    }
     1851
     1852    /* Then insert the real signing certificate. */
     1853    RTEXITCODE rcExit = SignToolPkcs7_AppendCertificate(pSignedData, pCertKeyPair->pCertificateReal);
     1854    if (rcExit != RTEXITCODE_SUCCESS)
     1855        return rcExit;
     1856
     1857    /*
     1858     * Modify the signer info to reflect the real certificate.
     1859     */
     1860    PRTCRPKCS7SIGNERINFO pSignerInfo = pSignedData->SignerInfos.papItems[0];
     1861    RTCrX509Name_Delete(&pSignerInfo->IssuerAndSerialNumber.Name);
     1862    int rc = RTCrX509Name_Clone(&pSignerInfo->IssuerAndSerialNumber.Name,
     1863                                &pCertKeyPair->pCertificateReal->TbsCertificate.Issuer, &g_RTAsn1DefaultAllocator);
     1864    if (RT_FAILURE(rc))
     1865        return RTMsgErrorExitFailure("(%s) RTCrX509Name_Clone failed: %Rrc", pszWhat, rc);
     1866
     1867    RTAsn1Integer_Delete(&pSignerInfo->IssuerAndSerialNumber.SerialNumber);
     1868    rc = RTAsn1Integer_Clone(&pSignerInfo->IssuerAndSerialNumber.SerialNumber,
     1869                             &pCertKeyPair->pCertificateReal->TbsCertificate.SerialNumber, &g_RTAsn1DefaultAllocator);
     1870    if (RT_FAILURE(rc))
     1871        return RTMsgErrorExitFailure("(%s) RTAsn1Integer_Clone failed: %Rrc", pszWhat, rc);
     1872
     1873    /* There shouldn't be anything in the authenticated attributes that
     1874       we need to modify... */
     1875
     1876    /*
     1877     * Now a create a new signature using the real key.  Since we haven't modified
     1878     * the authenticated attributes, we can just hash them as-is.
     1879     */
     1880    /* Create the hash to sign. */
     1881    RTCRDIGEST hDigest;
     1882    rc = RTCrDigestCreateByObjId(&hDigest, &pSignerInfo->DigestAlgorithm.Algorithm);
     1883    if (RT_FAILURE(rc))
     1884        return RTMsgErrorExitFailure("(%s) RTCrDigestCreateByObjId failed on '%s': %Rrc",
     1885                                     pszWhat, pSignerInfo->DigestAlgorithm.Algorithm.szObjId, rc);
     1886
     1887    rcExit = RTEXITCODE_FAILURE;
     1888    RTERRINFOSTATIC ErrInfo;
     1889    rc = RTCrPkcs7Attributes_HashAttributes(&pSignerInfo->AuthenticatedAttributes, hDigest, RTErrInfoInitStatic(&ErrInfo));
     1890    if (RT_SUCCESS(rc))
     1891    {
     1892        BCRYPT_PKCS1_PADDING_INFO PaddingInfo = { GetBCryptNameFromCrDigest(hDigest) };
     1893        DWORD                     cbSignature = 0;
     1894        SECURITY_STATUS rcNCrypt = NCryptSignHash(pCertKeyPair->hNCryptPrivateKey, &PaddingInfo,
     1895                                                  (PBYTE)RTCrDigestGetHash(hDigest), RTCrDigestGetHashSize(hDigest),
     1896                                                  NULL, 0, &cbSignature, NCRYPT_SILENT_FLAG | BCRYPT_PAD_PKCS1);
     1897        if (rcNCrypt == ERROR_SUCCESS)
     1898        {
     1899            if (cVerbosity)
     1900                RTMsgInfo("PaddingInfo: '%ls' cb=%#x, was %#zx\n",
     1901                          PaddingInfo.pszAlgId, cbSignature, pSignerInfo->EncryptedDigest.Asn1Core.cb);
     1902
     1903            rc = RTAsn1OctetString_AllocContent(&pSignerInfo->EncryptedDigest, NULL /*pvSrc*/, cbSignature,
     1904                                                &g_RTAsn1DefaultAllocator);
     1905            if (RT_SUCCESS(rc))
     1906            {
     1907                Assert(pSignerInfo->EncryptedDigest.Asn1Core.uData.pv);
     1908                rcNCrypt = NCryptSignHash(pCertKeyPair->hNCryptPrivateKey, &PaddingInfo,
     1909                                          (PBYTE)RTCrDigestGetHash(hDigest), RTCrDigestGetHashSize(hDigest),
     1910                                          (PBYTE)pSignerInfo->EncryptedDigest.Asn1Core.uData.pv, cbSignature, &cbSignature,
     1911                                          /*NCRYPT_SILENT_FLAG |*/ BCRYPT_PAD_PKCS1);
     1912                if (rcNCrypt == ERROR_SUCCESS)
     1913                {
     1914                    /*
     1915                     * Now we need to re-encode the whole thing and decode it again.
     1916                     */
     1917                    PRTASN1CORE pRoot = RTCrPkcs7ContentInfo_GetAsn1Core(pContentInfo);
     1918                    uint32_t    cbRealSigned;
     1919                    rc = RTAsn1EncodePrepare(pRoot, RTASN1ENCODE_F_DER, &cbRealSigned, RTErrInfoInitStatic(&ErrInfo));
     1920                    if (RT_SUCCESS(rc))
     1921                    {
     1922                        void *pvRealSigned = RTMemAllocZ(cbRealSigned);
     1923                        if (pvRealSigned)
     1924                        {
     1925                            rc = RTAsn1EncodeToBuffer(pRoot, RTASN1ENCODE_F_DER, pvRealSigned, cbRealSigned,
     1926                                                      RTErrInfoInitStatic(&ErrInfo));
     1927                            if (RT_SUCCESS(rc))
     1928                            {
     1929                                /* Decode it */
     1930                                RTCrPkcs7ContentInfo_Delete(pContentInfo);
     1931
     1932                                RTASN1CURSORPRIMARY PrimaryCursor;
     1933                                RTAsn1CursorInitPrimary(&PrimaryCursor, pvRealSigned, cbRealSigned, RTErrInfoInitStatic(&ErrInfo),
     1934                                                        &g_RTAsn1DefaultAllocator, 0, pszWhat);
     1935                                rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, pContentInfo, "CI");
     1936                                if (RT_SUCCESS(rc))
     1937                                {
     1938                                    Assert(RTCrPkcs7ContentInfo_IsSignedData(pContentInfo));
     1939
     1940                                    /* Almost done! Just replace output buffer. */
     1941                                    RTMemFree(*ppvSigned);
     1942                                    *ppvSigned = pvRealSigned;
     1943                                    *pcbSigned = cbRealSigned;
     1944                                    pvRealSigned = NULL;
     1945                                    rcExit = RTEXITCODE_SUCCESS;
     1946                                }
     1947                                else
     1948                                    RTMsgError("(%s) RTCrPkcs7ContentInfo_DecodeAsn1 failed: %Rrc%#RTeim",
     1949                                               pszWhat, rc, &ErrInfo.Core);
     1950                            }
     1951                            else
     1952                                RTMsgError("(%s) RTAsn1EncodeToBuffer failed: %Rrc%#RTeim", pszWhat, rc, &ErrInfo.Core);
     1953
     1954                            RTMemFree(pvRealSigned);
     1955                        }
     1956                        else
     1957                            RTMsgError("(%s) Failed to allocate %u bytes!", pszWhat, cbRealSigned);
     1958                    }
     1959                    else
     1960                        RTMsgError("(%s) RTAsn1EncodePrepare failed: %Rrc%#RTeim", pszWhat, rc, &ErrInfo.Core);
     1961                }
     1962                else
     1963                    RTMsgError("(%s) NCryptSignHash/2 failed: %Rwc %#x (%u)", pszWhat, rcNCrypt, rcNCrypt, rcNCrypt);
     1964            }
     1965            else
     1966                RTMsgError("(%s) RTAsn1OctetString_AllocContent(,,%#x) failed: %Rrc", pszWhat, cbSignature, rc);
     1967        }
     1968        else
     1969            RTMsgError("(%s) NCryptSignHash/1 failed: %Rwc %#x (%u)", pszWhat, rcNCrypt, rcNCrypt, rcNCrypt);
     1970    }
     1971    else
     1972        RTMsgError("(%s) RTCrPkcs7Attributes_HashAttributes failed: %Rrc%#RTeim", pszWhat, rc, &ErrInfo.Core);
     1973    RTCrDigestRelease(hDigest);
     1974    return rcExit;
     1975}
     1976
     1977#endif /* RT_OS_WINDOWS */
    12391978
    12401979static RTEXITCODE SignToolPkcs7_Pkcs7SignStuff(const char *pszWhat, const void *pvToDataToSign, size_t cbToDataToSign,
    12411980                                               PCRTCRPKCS7ATTRIBUTES pAuthAttribs, RTCRSTORE hAdditionalCerts,
    1242                                                uint32_t fExtraFlags, RTDIGESTTYPE enmDigestType, SIGNTOOLKEYPAIR *pCertKeyPair,
     1981                                               uint32_t fExtraFlags, RTDIGESTTYPE enmDigestType, SignToolKeyPair *pCertKeyPair,
    12431982                                               unsigned cVerbosity, void **ppvSigned, size_t *pcbSigned,
    12441983                                               PRTCRPKCS7CONTENTINFO pContentInfo, PRTCRPKCS7SIGNEDDATA *ppSignedData)
     
    12581997                                           NULL, &cbSigned, RTErrInfoInitStatic(&ErrInfo));
    12591998    if (rc != VERR_BUFFER_OVERFLOW)
    1260         return RTMsgErrorExitFailure("RTCrPkcs7SimpleSignSignedData failed: %Rrc%#RTeim", rc, &ErrInfo.Core);
     1999        return RTMsgErrorExitFailure("(%s) RTCrPkcs7SimpleSignSignedData failed: %Rrc%#RTeim", pszWhat, rc, &ErrInfo.Core);
    12612000
    12622001    /* Allocate memory for it and do the actual signing. */
    12632002    void *pvSigned = RTMemAllocZ(cbSigned);
    12642003    if (!pvSigned)
    1265         return RTMsgErrorExitFailure("Failed to allocate %#zx bytes for %s signature", cbSigned, pszWhat);
     2004        return RTMsgErrorExitFailure("(%s) Failed to allocate %#zx bytes for %s signature", pszWhat, cbSigned, pszWhat);
    12662005    rc = RTCrPkcs7SimpleSignSignedData(fSignFlags, pCertKeyPair->pCertificate, pCertKeyPair->hPrivateKey,
    12672006                                       pvToDataToSign, cbToDataToSign, enmDigestType, hAdditionalCerts, pAuthAttribs,
     
    12832022            if (RTCrPkcs7ContentInfo_IsSignedData(pContentInfo))
    12842023            {
    1285                 *ppvSigned = pvSigned;
    1286                 if (pcbSigned)
    1287                     *pcbSigned = cbSigned;
    1288                 if (ppSignedData)
    1289                     *ppSignedData = pContentInfo->u.pSignedData;
    1290 
    1291                 if (cVerbosity)
     2024#ifdef RT_OS_WINDOWS
     2025                /*
     2026                 * If we're using a fake key+cert, we now have to re-do the signing using the real
     2027                 * key+cert and the windows crypto API.   This kludge is necessary because we can't
     2028                 * typically get that the encoded private key, so it isn't possible to feed it to
     2029                 * openssl.
     2030                 */
     2031                RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     2032                if (pCertKeyPair->pCertificateReal)
     2033                    rcExit = SignToolPkcs7_Pkcs7SignStuffAgainWithReal(pszWhat, pCertKeyPair, cVerbosity, pContentInfo,
     2034                                                                       &pvSigned, &cbSigned);
     2035                if (rcExit == RTEXITCODE_SUCCESS)
     2036#endif
    12922037                {
    1293                     SHOWEXEPKCS7 ShowExe;
    1294                     RT_ZERO(ShowExe);
    1295                     ShowExe.cVerbosity = cVerbosity;
    1296                     HandleShowExeWorkerPkcs7Display(&ShowExe, pContentInfo->u.pSignedData, 0, pContentInfo);
     2038                    /*
     2039                     * Set returns and maybe display the result before returning.
     2040                     */
     2041                    *ppvSigned = pvSigned;
     2042                    if (pcbSigned)
     2043                        *pcbSigned = cbSigned;
     2044                    if (ppSignedData)
     2045                        *ppSignedData = pContentInfo->u.pSignedData;
     2046
     2047                    if (cVerbosity)
     2048                    {
     2049                        SHOWEXEPKCS7 ShowExe;
     2050                        RT_ZERO(ShowExe);
     2051                        ShowExe.cVerbosity = cVerbosity;
     2052                        HandleShowExeWorkerPkcs7Display(&ShowExe, pContentInfo->u.pSignedData, 0, pContentInfo);
     2053                    }
     2054                    return RTEXITCODE_SUCCESS;
    12972055                }
    1298                 return RTEXITCODE_SUCCESS;
    12992056            }
    13002057
    1301             RTMsgError("RTCrPkcs7SimpleSignSignedData did not create SignedData: %s", pContentInfo->ContentType.szObjId);
     2058            RTMsgError("(%s) RTCrPkcs7SimpleSignSignedData did not create SignedData: %s",
     2059                       pszWhat, pContentInfo->ContentType.szObjId);
    13022060        }
    13032061        else
    1304             RTMsgError("RTCrPkcs7ContentInfo_DecodeAsn1 failed: %Rrc%#RTeim", rc, &ErrInfo.Core);
     2062            RTMsgError("(%s) RTCrPkcs7ContentInfo_DecodeAsn1 failed: %Rrc%#RTeim", pszWhat, rc, &ErrInfo.Core);
    13052063        RTCrPkcs7ContentInfo_Delete(pContentInfo);
    13062064    }
     
    13122070static RTEXITCODE SignToolPkcs7_AddTimestampSignatureEx(PRTCRPKCS7SIGNERINFO pSignerInfo, PRTCRPKCS7SIGNEDDATA pSignedData,
    13132071                                                        unsigned cVerbosity,  bool fReplaceExisting, bool fTimestampTypeOld,
    1314                                                         RTTIMESPEC SigningTime, SIGNTOOLKEYPAIR *pTimestampPair)
     2072                                                        RTTIMESPEC SigningTime, SignToolKeyPair *pTimestampPair)
    13152073{
    13162074    AssertReturn(fTimestampTypeOld, RTMsgErrorExitFailure("New style signatures not supported yet"));
     
    13902148static RTEXITCODE SignToolPkcs7_AddTimestampSignature(SIGNTOOLPKCS7EXE *pThis, unsigned cVerbosity, unsigned iSignature,
    13912149                                                      bool fReplaceExisting, bool fTimestampTypeOld, RTTIMESPEC SigningTime,
    1392                                                       SIGNTOOLKEYPAIR *pTimestampPair)
     2150                                                      SignToolKeyPair *pTimestampPair)
    13932151{
    13942152    AssertReturn(fTimestampTypeOld, RTMsgErrorExitFailure("New style signatures not supported yet"));
     
    14092167static RTEXITCODE SignToolPkcs7_SignData(SIGNTOOLPKCS7 *pThis, PRTASN1CORE pToSignRoot, bool fIsRootsParent,
    14102168                                         const char *pszContentTypeId, unsigned cVerbosity,  RTDIGESTTYPE enmSigType,
    1411                                          bool fReplaceExisting, SIGNTOOLKEYPAIR *pSigningCertKey, RTCRSTORE hAddCerts,
    1412                                          bool fTimestampTypeOld, RTTIMESPEC SigningTime, SIGNTOOLKEYPAIR *pTimestampCertKey)
     2169                                         bool fReplaceExisting, SignToolKeyPair *pSigningCertKey, RTCRSTORE hAddCerts,
     2170                                         bool fTimestampTypeOld, RTTIMESPEC SigningTime, SignToolKeyPair *pTimestampCertKey)
    14132171{
    14142172    /*
     
    17122470
    17132471static RTEXITCODE SignToolPkcs7_AddOrReplaceSignature(SIGNTOOLPKCS7EXE *pThis, unsigned cVerbosity, RTDIGESTTYPE enmSigType,
    1714                                                       bool fReplaceExisting,  bool fHashPages, SIGNTOOLKEYPAIR *pSigningCertKey,
     2472                                                      bool fReplaceExisting,  bool fHashPages, SignToolKeyPair *pSigningCertKey,
    17152473                                                      RTCRSTORE hAddCerts,  bool fTimestampTypeOld,
    1716                                                       RTTIMESPEC SigningTime, SIGNTOOLKEYPAIR *pTimestampCertKey)
     2474                                                      RTTIMESPEC SigningTime, SignToolKeyPair *pTimestampCertKey)
    17172475{
    17182476    AssertReturn(fTimestampTypeOld || pTimestampCertKey->isNull(),
     
    17982556
    17992557static RTEXITCODE SignToolPkcs7_AddOrReplaceCatSignature(SIGNTOOLPKCS7 *pThis, unsigned cVerbosity, RTDIGESTTYPE enmSigType,
    1800                                                          bool fReplaceExisting, SIGNTOOLKEYPAIR *pSigningCertKey,
     2558                                                         bool fReplaceExisting, SignToolKeyPair *pSigningCertKey,
    18012559                                                         RTCRSTORE hAddCerts, bool fTimestampTypeOld,
    1802                                                          RTTIMESPEC SigningTime, SIGNTOOLKEYPAIR *pTimestampCertKey)
     2560                                                         RTTIMESPEC SigningTime, SignToolKeyPair *pTimestampCertKey)
    18032561{
    18042562    AssertReturn(fTimestampTypeOld || pTimestampCertKey->isNull(),
     
    22983056#ifndef IPRT_IN_BUILD_TOOL
    22993057
    2300 static RTEXITCODE HandleOptCertFile(SIGNTOOLKEYPAIR *pKeyPair, const char *pszFile)
    2301 {
    2302     if (pKeyPair->pCertificate == &pKeyPair->Cert)
    2303         RTCrX509Certificate_Delete(&pKeyPair->Cert);
    2304     pKeyPair->pCertificate = NULL;
    2305 
    2306     RTERRINFOSTATIC ErrInfo;
    2307     int rc = RTCrX509Certificate_ReadFromFile(&pKeyPair->Cert, pszFile, 0, &g_RTAsn1DefaultAllocator,
    2308                                               RTErrInfoInitStatic(&ErrInfo));
    2309     if (RT_FAILURE(rc))
    2310         return RTMsgErrorExitFailure("Error reading certificate from '%s': %Rrc%#RTeim", pszFile, rc, &ErrInfo.Core);
    2311     pKeyPair->pCertificate = &pKeyPair->Cert;
    2312     return RTEXITCODE_SUCCESS;
    2313 }
    2314 
    2315 static RTEXITCODE HandleOptKeyFile(SIGNTOOLKEYPAIR *pKeyPair, const char *pszFile)
    2316 {
    2317     RTCrKeyRelease(pKeyPair->hPrivateKey);
    2318 
    2319     RTERRINFOSTATIC ErrInfo;
    2320     int rc = RTCrKeyCreateFromFile(&pKeyPair->hPrivateKey, 0 /*fFlags*/, pszFile,
    2321                                    NULL /*pszPassword*/, RTErrInfoInitStatic(&ErrInfo));
    2322     if (RT_SUCCESS(rc))
    2323         return RTEXITCODE_SUCCESS;
    2324 
    2325     pKeyPair->hPrivateKey = NIL_RTCRKEY;
    2326     return RTMsgErrorExitFailure("Error reading private key from '%s': %Rrc%#RTeim", pszFile, rc, &ErrInfo.Core);
    2327 }
    2328 
    23293058static RTEXITCODE HandleOptAddCert(PRTCRSTORE phStore, const char *pszFile)
    23303059{
     
    24453174    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
    24463175                        "add-timestamp-exe-signature [-v|--verbose] [--signature-index|-i <num>] "
    2447                         "[--timestamp-cert-file <file>] "
    2448                         "[--timestamp-key-file <file>] "
     3176                        OPT_CERT_KEY_SYNOPSIS("--timestamp-")
    24493177                        "[--timestamp-type old|new] "
    24503178                        "[--timestamp-date <fake-isots>] "
     
    24703198    {
    24713199        { "--signature-index",      'i',                        RTGETOPT_REQ_UINT32 },
    2472         { "--timestamp-cert-file",  OPT_TIMESTAMP_CERT_FILE,    RTGETOPT_REQ_STRING },
    2473         { "--timestamp-key-file",   OPT_TIMESTAMP_KEY_FILE,     RTGETOPT_REQ_STRING },
     3200        OPT_CERT_KEY_GETOPTDEF_ENTRIES("--timestamp-", 1000),
    24743201        { "--timestamp-type",       OPT_TIMESTAMP_TYPE,         RTGETOPT_REQ_STRING },
    24753202        { "--timestamp-override",   OPT_TIMESTAMP_OVERRIDE,     RTGETOPT_REQ_STRING },
     
    24823209    bool                    fReplaceExisting        = false;
    24833210    bool                    fTimestampTypeOld       = true;
    2484     SIGNTOOLKEYPAIR         TimestampCertKey;
     3211    SignToolKeyPair         TimestampCertKey("timestamp", true);
    24853212    RTTIMESPEC              SigningTime;
    24863213    RTTimeNow(&SigningTime);
     
    24983225        switch (ch)
    24993226        {
     3227            OPT_CERT_KEY_SWITCH_CASES(TimestampCertKey, 1000, ch, ValueUnion, rcExit2);
    25003228            case 'i':                       iSignature = ValueUnion.u32; break;
    2501             case OPT_TIMESTAMP_CERT_FILE:   rcExit2 = HandleOptCertFile(&TimestampCertKey, ValueUnion.psz); break;
    2502             case OPT_TIMESTAMP_KEY_FILE:    rcExit2 = HandleOptKeyFile(&TimestampCertKey, ValueUnion.psz); break;
    25033229            case OPT_TIMESTAMP_TYPE:        rcExit2 = HandleOptTimestampType(&fTimestampTypeOld, ValueUnion.psz); break;
    25043230            case OPT_TIMESTAMP_OVERRIDE:    rcExit2 = HandleOptTimestampOverride(&SigningTime, ValueUnion.psz); break;
     
    25093235
    25103236            case VINF_GETOPT_NOT_OPTION:
    2511                 /* check that we've got all the info we need: */
    2512                 if (TimestampCertKey.isComplete())
     3237                /* Do final certificate and key option processing (first file only). */
     3238                rcExit2 = TimestampCertKey.finalizeOptions(cVerbosity);
     3239                if (rcExit2 == RTEXITCODE_SUCCESS)
    25133240                {
    25143241                    /* Do the work: */
     
    25293256                    rcExit2 = RTEXITCODE_SUCCESS;
    25303257                }
    2531                 else
    2532                 {
    2533                     if (!TimestampCertKey.pCertificate)
    2534                         RTMsgError("No timestamp certificate was specified");
    2535                     if (TimestampCertKey.hPrivateKey == NIL_RTCRKEY)
    2536                         RTMsgError("No timestamp private key was specified");
    2537                     rcExit2 = RTEXITCODE_SYNTAX;
    2538                 }
    25393258                break;
    25403259
     
    25703289                        "[--no-hash-pages] "
    25713290                        "[--append] "
    2572                         "[--cert-file <file>] "
    2573                         "[--cert-key <file>] "
     3291                        OPT_CERT_KEY_SYNOPSIS("--")
    25743292                        "[--add-cert <file>] "
    2575                         "[--timestamp-cert-file <file>] "
    2576                         "[--timestamp-key-file <file>] "
     3293                        OPT_CERT_KEY_SYNOPSIS("--timestamp-")
    25773294                        "[--timestamp-type old|new] "
    25783295                        "[--timestamp-date <fake-isots>] "
     
    26083325        { "--add-cert",             OPT_ADD_CERT,               RTGETOPT_REQ_STRING },
    26093326        { "/ac",                    OPT_ADD_CERT,               RTGETOPT_REQ_STRING },
    2610         { "--cert-file",            OPT_CERT_FILE,              RTGETOPT_REQ_STRING },
    2611         { "--key-file",             OPT_KEY_FILE,               RTGETOPT_REQ_STRING },
    2612         { "--timestamp-cert-file",  OPT_TIMESTAMP_CERT_FILE,    RTGETOPT_REQ_STRING },
    2613         { "--timestamp-key-file",   OPT_TIMESTAMP_KEY_FILE,     RTGETOPT_REQ_STRING },
     3327        OPT_CERT_KEY_GETOPTDEF_ENTRIES("--",           1000),
     3328        OPT_CERT_KEY_GETOPTDEF_COMPAT_ENTRIES(         1000),
     3329        OPT_CERT_KEY_GETOPTDEF_ENTRIES("--timestamp-", 1020),
    26143330        { "--timestamp-type",       OPT_TIMESTAMP_TYPE,         RTGETOPT_REQ_STRING },
    26153331        { "--timestamp-override",   OPT_TIMESTAMP_OVERRIDE,     RTGETOPT_REQ_STRING },
     
    26233339    bool                    fReplaceExisting        = true;
    26243340    bool                    fHashPages              = false;
    2625     SIGNTOOLKEYPAIR         SigningCertKey;
     3341    SignToolKeyPair         SigningCertKey("signing", true);
    26263342    RTCRSTORE               hAddCerts               = NIL_RTCRSTORE; /* leaked if returning directly (--help, --version) */
    26273343    bool                    fTimestampTypeOld       = true;
    2628     SIGNTOOLKEYPAIR         TimestampCertKey;
     3344    SignToolKeyPair         TimestampCertKey("timestamp");
    26293345    RTTIMESPEC              SigningTime;
    26303346    RTTimeNow(&SigningTime);
     
    26423358        switch (ch)
    26433359        {
     3360            OPT_CERT_KEY_SWITCH_CASES(SigningCertKey,   1000, ch, ValueUnion, rcExit2);
     3361            OPT_CERT_KEY_SWITCH_CASES(TimestampCertKey, 1020, ch, ValueUnion, rcExit2);
    26443362            case 't':                       rcExit2 = HandleOptSignatureType(&enmSigType, ValueUnion.psz); break;
    26453363            case 'a':                       fReplaceExisting = false; break;
    26463364            case OPT_HASH_PAGES:            fHashPages = true; break;
    26473365            case OPT_NO_HASH_PAGES:         fHashPages = false; break;
    2648             case OPT_CERT_FILE:             rcExit2 = HandleOptCertFile(&SigningCertKey, ValueUnion.psz); break;
    2649             case OPT_KEY_FILE:              rcExit2 = HandleOptKeyFile(&SigningCertKey, ValueUnion.psz); break;
    26503366            case OPT_ADD_CERT:              rcExit2 = HandleOptAddCert(&hAddCerts, ValueUnion.psz); break;
    2651             case OPT_TIMESTAMP_CERT_FILE:   rcExit2 = HandleOptCertFile(&TimestampCertKey, ValueUnion.psz); break;
    2652             case OPT_TIMESTAMP_KEY_FILE:    rcExit2 = HandleOptKeyFile(&TimestampCertKey, ValueUnion.psz); break;
    26533367            case OPT_TIMESTAMP_TYPE:        rcExit2 = HandleOptTimestampType(&fTimestampTypeOld, ValueUnion.psz); break;
    26543368            case OPT_TIMESTAMP_OVERRIDE:    rcExit2 = HandleOptTimestampOverride(&SigningTime, ValueUnion.psz); break;
     
    26583372
    26593373            case VINF_GETOPT_NOT_OPTION:
    2660                 /* check that we've got all the info we need: */
    2661                 if (   SigningCertKey.isComplete()
    2662                     && (TimestampCertKey.isNull() || TimestampCertKey.isComplete()))
     3374                /* Do final certificate and key option processing (first file only). */
     3375                rcExit2 = SigningCertKey.finalizeOptions(cVerbosity);
     3376                if (rcExit2 == RTEXITCODE_SUCCESS)
     3377                    rcExit2 = TimestampCertKey.finalizeOptions(cVerbosity);
     3378                if (rcExit2 == RTEXITCODE_SUCCESS)
    26633379                {
    26643380                    /* Do the work: */
     
    26813397                    rcExit2 = RTEXITCODE_SUCCESS;
    26823398                }
    2683                 else
    2684                 {
    2685                     if (!TimestampCertKey.pCertificate)
    2686                         RTMsgError("No signing certificate was specified");
    2687                     if (TimestampCertKey.hPrivateKey == NIL_RTCRKEY)
    2688                         RTMsgError("No signing private key was specified");
    2689 
    2690                     if (!TimestampCertKey.pCertificate && !TimestampCertKey.isNull())
    2691                         RTMsgError("No timestamp certificate was specified");
    2692                     if (TimestampCertKey.hPrivateKey == NIL_RTCRKEY && !TimestampCertKey.isNull())
    2693                         RTMsgError("No timestamp private key was specified");
    2694                     rcExit2 = RTEXITCODE_SYNTAX;
    2695                 }
    26963399                break;
    26973400
     
    27243427
    27253428    RTStrmWrappedPrintf(pStrm, RTSTRMWRAPPED_F_HANGING_INDENT,
    2726                         "sign-exe [-v|--verbose] "
     3429                        "sign-cat [-v|--verbose] "
    27273430                        "[--type sha1|sha256] "
    27283431                        "[--append] "
    2729                         "[--cert-file <file>] "
    2730                         "[--cert-key <file>] "
     3432                        OPT_CERT_KEY_SYNOPSIS("--")
    27313433                        "[--add-cert <file>] "
    2732                         "[--timestamp-cert-file <file>] "
    2733                         "[--timestamp-key-file <file>] "
     3434                        OPT_CERT_KEY_SYNOPSIS("--timestamp-")
    27343435                        "[--timestamp-type old|new] "
    27353436                        "[--timestamp-date <fake-isots>] "
     
    27613462        { "--add-cert",             OPT_ADD_CERT,               RTGETOPT_REQ_STRING },
    27623463        { "/ac",                    OPT_ADD_CERT,               RTGETOPT_REQ_STRING },
    2763         { "--cert-file",            OPT_CERT_FILE,              RTGETOPT_REQ_STRING },
    2764         { "--key-file",             OPT_KEY_FILE,               RTGETOPT_REQ_STRING },
    2765         { "--timestamp-cert-file",  OPT_TIMESTAMP_CERT_FILE,    RTGETOPT_REQ_STRING },
    2766         { "--timestamp-key-file",   OPT_TIMESTAMP_KEY_FILE,     RTGETOPT_REQ_STRING },
     3464        OPT_CERT_KEY_GETOPTDEF_ENTRIES("--",           1000),
     3465        OPT_CERT_KEY_GETOPTDEF_COMPAT_ENTRIES(         1000),
     3466        OPT_CERT_KEY_GETOPTDEF_ENTRIES("--timestamp-", 1020),
    27673467        { "--timestamp-type",       OPT_TIMESTAMP_TYPE,         RTGETOPT_REQ_STRING },
    27683468        { "--timestamp-override",   OPT_TIMESTAMP_OVERRIDE,     RTGETOPT_REQ_STRING },
     
    27753475    RTDIGESTTYPE            enmSigType              = RTDIGESTTYPE_SHA1;
    27763476    bool                    fReplaceExisting        = true;
    2777     SIGNTOOLKEYPAIR         SigningCertKey;
     3477    SignToolKeyPair         SigningCertKey("signing", true);
    27783478    RTCRSTORE               hAddCerts               = NIL_RTCRSTORE; /* leaked if returning directly (--help, --version) */
    27793479    bool                    fTimestampTypeOld       = true;
    2780     SIGNTOOLKEYPAIR         TimestampCertKey;
     3480    SignToolKeyPair         TimestampCertKey("timestamp");
    27813481    RTTIMESPEC              SigningTime;
    27823482    RTTimeNow(&SigningTime);
     
    27943494        switch (ch)
    27953495        {
     3496            OPT_CERT_KEY_SWITCH_CASES(SigningCertKey,   1000, ch, ValueUnion, rcExit2);
     3497            OPT_CERT_KEY_SWITCH_CASES(TimestampCertKey, 1020, ch, ValueUnion, rcExit2);
    27963498            case 't':                       rcExit2 = HandleOptSignatureType(&enmSigType, ValueUnion.psz); break;
    27973499            case 'a':                       fReplaceExisting = false; break;
    2798             case OPT_CERT_FILE:             rcExit2 = HandleOptCertFile(&SigningCertKey, ValueUnion.psz); break;
    2799             case OPT_KEY_FILE:              rcExit2 = HandleOptKeyFile(&SigningCertKey, ValueUnion.psz); break;
    28003500            case OPT_ADD_CERT:              rcExit2 = HandleOptAddCert(&hAddCerts, ValueUnion.psz); break;
    2801             case OPT_TIMESTAMP_CERT_FILE:   rcExit2 = HandleOptCertFile(&TimestampCertKey, ValueUnion.psz); break;
    2802             case OPT_TIMESTAMP_KEY_FILE:    rcExit2 = HandleOptKeyFile(&TimestampCertKey, ValueUnion.psz); break;
    28033501            case OPT_TIMESTAMP_TYPE:        rcExit2 = HandleOptTimestampType(&fTimestampTypeOld, ValueUnion.psz); break;
    28043502            case OPT_TIMESTAMP_OVERRIDE:    rcExit2 = HandleOptTimestampOverride(&SigningTime, ValueUnion.psz); break;
     
    28083506
    28093507            case VINF_GETOPT_NOT_OPTION:
    2810                 /* check that we've got all the info we need: */
    2811                 if (   SigningCertKey.isComplete()
    2812                     && (TimestampCertKey.isNull() || TimestampCertKey.isComplete()))
     3508                /* Do final certificate and key option processing (first file only). */
     3509                rcExit2 = SigningCertKey.finalizeOptions(cVerbosity);
     3510                if (rcExit2 == RTEXITCODE_SUCCESS)
     3511                    rcExit2 = TimestampCertKey.finalizeOptions(cVerbosity);
     3512                if (rcExit2 == RTEXITCODE_SUCCESS)
    28133513                {
    28143514                    /* Do the work: */
     
    28293529                        rcExit = rcExit2;
    28303530                    rcExit2 = RTEXITCODE_SUCCESS;
    2831                 }
    2832                 else
    2833                 {
    2834                     if (!TimestampCertKey.pCertificate)
    2835                         RTMsgError("No signing certificate was specified");
    2836                     if (TimestampCertKey.hPrivateKey == NIL_RTCRKEY)
    2837                         RTMsgError("No signing private key was specified");
    2838 
    2839                     if (!TimestampCertKey.pCertificate && !TimestampCertKey.isNull())
    2840                         RTMsgError("No timestamp certificate was specified");
    2841                     if (TimestampCertKey.hPrivateKey == NIL_RTCRKEY && !TimestampCertKey.isNull())
    2842                         RTMsgError("No timestamp private key was specified");
    2843                     rcExit2 = RTEXITCODE_SYNTAX;
    28443531                }
    28453532                break;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette