Skip to content

Commit

Permalink
Add -X flag for seperate pkcs11 uri for Certificate
Browse files Browse the repository at this point in the history
Ex:
ldid -K'pkcs11:object=MyKey;type=private' -X'pkcs11:object=MyKey;type=cert'
ldid -KCertificates.p12 -XExtractedFromP12.cer -XAppleWWDRCAG3.cer -XAppleIncRootCertificate.cer
  • Loading branch information
CRKatri committed Jun 26, 2024
1 parent 88b05b3 commit 798f55b
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 54 deletions.
4 changes: 2 additions & 2 deletions PKCS11.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ yubico-piv-tool -s 9c -a import-certificate -i cert.crt.pem
yubico-piv-tool -s 9c -a import-key -i key.pem
yubico-piv-tool -s 9c -a set-chuid
```
3. You can use `p11tool --list-privkeys --login` to identify the URI for the slot (make sure that `type` is not in the URI, as seperate URIs for the cert and private key are not currently supported from the command line)
3. You can use `p11tool --list-privkeys --login` and `p11tool --list-certs --login` to help identify the URIs for the private key and certificate

## Sign
1. `ldid -K'pkcs11:model=YubiKey%20YK5;id=%02' -Sents.xml ls.bin`
1. `ldid -K'pkcs11:object=Private%20key%20for%20Digital%20Signature;type=private' -X'pkcs11:object=X.509%20Certificate%20for%20Digital%20Signature;type=cert' -Sents.xml ls.bin`
2. If the correct PKCS#11 module is not being loaded, try setting `PKCS11_MODULE_PATH` in your environment (ex. `export PKCS11_MODULE_PATH="/usr/local/lib/p11-kit-proxy.so"` or `PKCS11_MODULE_PATH="/usr/local/lib/libykcs11.so"`)
16 changes: 15 additions & 1 deletion docs/ldid.1
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
.Op Fl H Ns Op Ar sha1 | Ar sha256
.Op Fl h
.Op Fl I Ns Ar name
.Op Fl K Ns Ar file Op Fl U Ns Ar password
.Op Fl K Ns Ar file Oo Fl U Ns Ar password Oc Op Fl X Ns Ar file
.Op Fl M
.Op Fl P Ns Op Ar num
.Op Fl Q Ns Ar requirements
Expand Down Expand Up @@ -108,6 +108,8 @@ If the
has a password, you will be prompted for it,
or you can specify from the command line with
.Fl U .
To specify the certificate separate from the private key, use
.Fl X .
.It Fl M
When used with
.Fl S ,
Expand Down Expand Up @@ -160,6 +162,18 @@ target is a bundle directory, and not a specific Mach-O file.
.Fl w
can be used on any bundle, not just the root .app, including frameworks,
appexes, and more.
.It Fl X Ns Ar file
Adds
.Ar file
as a certificate to be used when signing.
The first
.Ar file
must be the certificate for the signing key, each additional will be added as part of the chain.
Must be either
.Ar DER
encoded certificate or
.Ar pkcs11:
URI.
.El
.Sh EXAMPLES
To fakesign
Expand Down
157 changes: 106 additions & 51 deletions ldid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
#include <sys/stat.h>
#include <sys/types.h>

# if SMARTCARD
# define OPENSSL_SUPPRESS_DEPRECATED
/* We need to use engines, which are deprecated */
# endif

#include <openssl/opensslv.h>
# if OPENSSL_VERSION_MAJOR >= 3
# include <openssl/provider.h>
Expand Down Expand Up @@ -1867,7 +1872,7 @@ class P12Signer : public ldid::Signer {
STACK_OF(X509) *ca_;

public:
P12Signer(BIO *bio) :
P12Signer(BIO *bio, std::vector<std::string> certs) :
value_(d2i_PKCS12_bio(bio, NULL)),
key_(NULL),
cert_(NULL),
Expand All @@ -1888,7 +1893,7 @@ class P12Signer : public ldid::Signer {
fprintf(stderr, "ldid: An error occured while parsing: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
if (key_ == NULL || cert_ == NULL) {
if (key_ == NULL || (cert_ == NULL && certs.empty())) {
fprintf(stderr, "ldid: An error occured while parsing: %s\nYour p12 cert might not be valid\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
Expand All @@ -1899,6 +1904,22 @@ class P12Signer : public ldid::Signer {
fprintf(stderr, "ldid: An error occured while parsing: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}

if (!certs.empty()) {
cert_ = d2i_X509_bio(Buffer(Map(certs[0], false)), NULL);
certs.erase(certs.begin());
_foreach (certid, certs) {
X509 *cert = d2i_X509_bio(Buffer(Map(certid, false)), NULL);
if (cert == NULL) {
fprintf(stderr, "ldid: An error occured while parsing: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
if (sk_X509_push(ca_, cert) == 0) {
fprintf(stderr, "ldid: An error occured while loading: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
}
}
}

~P12Signer() {
Expand Down Expand Up @@ -1932,16 +1953,63 @@ class P11Signer : public ldid::Signer {
EVP_PKEY *key_;
X509 *cert_;
STACK_OF(X509) *ca_;
bool supportLoadCert = false;

X509 *loadcert(std::string cert_id) {
if (cert_id.compare(0, 7, "pkcs11:") == 0) {
const char *cmd_name = "LOAD_CERT_CTRL";
struct {
const char *cert_id;
X509 *cert;
} params;

params.cert_id = cert_id.c_str();
params.cert = NULL;

if (!supportLoadCert) {
if (ENGINE_ctrl(e_, ENGINE_CTRL_GET_CMD_FROM_NAME, 0, (void *)cmd_name, NULL) == 0) {
fprintf(stderr, "ldid: Engine does not support loading certificate: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
supportLoadCert = true;
}

if (ENGINE_ctrl_cmd(e_, cmd_name, 0, &params, NULL, 1) == 0) {
fprintf(stderr, "ldid: Engine cannot load certificate: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}

if (params.cert == NULL) {
fprintf(stderr, "ldid: An error occured while loading: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}

return params.cert;
} else {
X509 *cert = d2i_X509_bio(Buffer(Map(cert_id, false)), NULL);
if (cert == NULL) {
fprintf(stderr, "ldid: An error occured while loading: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}

return cert;
}
}

public:
P11Signer(std::string uri)
: P11Signer(uri, uri) {}
: P11Signer(uri, {}) {}

P11Signer(std::string keyuri, std::string certuri) :
P11Signer(std::string keyuri, std::vector<std::string> certs) :
key_(NULL),
cert_(NULL),
ca_(NULL)
ca_(sk_X509_new_null())
{
if (ca_ == NULL) {
fprintf(stderr, "ldid: An error occured while loading: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}

e_ = ENGINE_by_id("pkcs11");
if (!e_) {
fprintf(stderr, "ldid: An error occured while loading pkcs11 engine: %s\n", ERR_error_string(ERR_get_error(), NULL));
Expand All @@ -1952,56 +2020,33 @@ class P11Signer : public ldid::Signer {
fprintf(stderr, "ldid: Failed to initialize pkcs11 engine: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
ENGINE_free(e_);
ENGINE_free(e_); // for ENGINE_by_id()

key_ = ENGINE_load_private_key(e_, keyuri.c_str(), NULL, NULL);
if (key_ == NULL){
fprintf(stderr, "ldid: An error occured while loading: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}

const char *cmd_name = "LOAD_CERT_CTRL";
struct {
const char *cert_id;
X509 *cert;
} params;

params.cert_id = certuri.c_str();
params.cert = NULL;

if (ENGINE_ctrl(e_, ENGINE_CTRL_GET_CMD_FROM_NAME, 0, (void *)cmd_name, NULL) == 0) {
fprintf(stderr, "ldid: Engine does not support loading certificate: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}

if (ENGINE_ctrl_cmd(e_, cmd_name, 0, &params, NULL, 1) == 0) {
fprintf(stderr, "ldid: Engine cannot load certificate: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}

cert_ = params.cert;

if (cert_ == NULL) {
fprintf(stderr, "ldid: An error occured while loading: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}

if (ca_ == NULL)
ca_ = sk_X509_new_null();
if (ca_ == NULL) {
fprintf(stderr, "ldid: An error occured while loading: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
if (certs.empty()) {
cert_ = loadcert(keyuri);
} else {
cert_ = loadcert(certs[0]);
certs.erase(certs.begin());
_foreach (certid, certs) {
if (sk_X509_push(ca_, loadcert(certid)) == 0) {
fprintf(stderr, "ldid: An error occured while loading: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
}
}
}

~P11Signer() {
sk_X509_pop_free(ca_, X509_free);
X509_free(cert_);
EVP_PKEY_free(key_);
if (e_) {
ENGINE_finish(e_);
ENGINE_free(e_);
}
ENGINE_finish(e_); // for ENGINE_init()
}

operator EVP_PKEY *() const {
Expand Down Expand Up @@ -3506,6 +3551,7 @@ int main(int argc, char *argv[]) {
Map entitlements;
Map requirements;
std::string key;
std::vector<std::string> certs;
ldid::Signer *signer = new NoSigner();
ldid::Slots slots;

Expand Down Expand Up @@ -3714,6 +3760,11 @@ int main(int argc, char *argv[]) {
key = argv[argi] + 2;
break;

case 'X':
if (argv[argi][2] != '\0')
certs.push_back(argv[argi] + 2);
break;

case 'T': break;

case 'u': {
Expand All @@ -3739,14 +3790,16 @@ int main(int argc, char *argv[]) {
return 0;

if (!key.empty()) {
#if SMARTCARD
delete signer;
if (key.compare(0, 7, "pkcs11:") == 0) {
signer = new P11Signer(key);
} else
#if SMARTCARD
signer = new P11Signer(key, certs);
#else
fprintf(stderr, "ldid: Smartcard support is not enabled\n");
exit(1);
#endif
{
signer = new P12Signer(Buffer(Map(key, O_RDONLY)));
}
} else
signer = new P12Signer(Buffer(Map(key, O_RDONLY, PROT_READ, MAP_PRIVATE)), certs);
}

size_t filei(0), filee(0);
Expand Down Expand Up @@ -4049,15 +4102,17 @@ int main(int argc, char *argv[]) {
++filei;
}

# if OPENSSL_VERSION_MAJOR >= 3
OSSL_PROVIDER_unload(legacy);
OSSL_PROVIDER_unload(deflt);
# endif
delete signer;

# if SMARTCARD
ENGINE_cleanup();
# endif

# if OPENSSL_VERSION_MAJOR >= 3
OSSL_PROVIDER_unload(legacy);
OSSL_PROVIDER_unload(deflt);
# endif

return filee;
}
#endif // LDID_NOTOOLS
Expand Down
1 change: 1 addition & 0 deletions ldid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ struct Bundle {

class Signer {
public:
virtual ~Signer() {};
virtual operator EVP_PKEY *() const = 0;
virtual operator X509 *() const = 0;
virtual operator STACK_OF(X509) *() const = 0;
Expand Down

0 comments on commit 798f55b

Please sign in to comment.