1*40863f4dSKP Singh // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2*40863f4dSKP Singh /* 3*40863f4dSKP Singh * Copyright (C) 2025 Google LLC. 4*40863f4dSKP Singh */ 5*40863f4dSKP Singh 6*40863f4dSKP Singh #ifndef _GNU_SOURCE 7*40863f4dSKP Singh #define _GNU_SOURCE 8*40863f4dSKP Singh #endif 9*40863f4dSKP Singh #include <stdio.h> 10*40863f4dSKP Singh #include <stdlib.h> 11*40863f4dSKP Singh #include <stdint.h> 12*40863f4dSKP Singh #include <stdbool.h> 13*40863f4dSKP Singh #include <string.h> 14*40863f4dSKP Singh #include <string.h> 15*40863f4dSKP Singh #include <getopt.h> 16*40863f4dSKP Singh #include <err.h> 17*40863f4dSKP Singh #include <openssl/opensslv.h> 18*40863f4dSKP Singh #include <openssl/bio.h> 19*40863f4dSKP Singh #include <openssl/evp.h> 20*40863f4dSKP Singh #include <openssl/pem.h> 21*40863f4dSKP Singh #include <openssl/err.h> 22*40863f4dSKP Singh #include <openssl/cms.h> 23*40863f4dSKP Singh #include <linux/keyctl.h> 24*40863f4dSKP Singh #include <errno.h> 25*40863f4dSKP Singh 26*40863f4dSKP Singh #include <bpf/skel_internal.h> 27*40863f4dSKP Singh 28*40863f4dSKP Singh #include "main.h" 29*40863f4dSKP Singh 30*40863f4dSKP Singh #define OPEN_SSL_ERR_BUF_LEN 256 31*40863f4dSKP Singh 32*40863f4dSKP Singh static void display_openssl_errors(int l) 33*40863f4dSKP Singh { 34*40863f4dSKP Singh char buf[OPEN_SSL_ERR_BUF_LEN]; 35*40863f4dSKP Singh const char *file; 36*40863f4dSKP Singh const char *data; 37*40863f4dSKP Singh unsigned long e; 38*40863f4dSKP Singh int flags; 39*40863f4dSKP Singh int line; 40*40863f4dSKP Singh 41*40863f4dSKP Singh while ((e = ERR_get_error_all(&file, &line, NULL, &data, &flags))) { 42*40863f4dSKP Singh ERR_error_string_n(e, buf, sizeof(buf)); 43*40863f4dSKP Singh if (data && (flags & ERR_TXT_STRING)) { 44*40863f4dSKP Singh p_err("OpenSSL %s: %s:%d: %s", buf, file, line, data); 45*40863f4dSKP Singh } else { 46*40863f4dSKP Singh p_err("OpenSSL %s: %s:%d", buf, file, line); 47*40863f4dSKP Singh } 48*40863f4dSKP Singh } 49*40863f4dSKP Singh } 50*40863f4dSKP Singh 51*40863f4dSKP Singh #define DISPLAY_OSSL_ERR(cond) \ 52*40863f4dSKP Singh do { \ 53*40863f4dSKP Singh bool __cond = (cond); \ 54*40863f4dSKP Singh if (__cond && ERR_peek_error()) \ 55*40863f4dSKP Singh display_openssl_errors(__LINE__);\ 56*40863f4dSKP Singh } while (0) 57*40863f4dSKP Singh 58*40863f4dSKP Singh static EVP_PKEY *read_private_key(const char *pkey_path) 59*40863f4dSKP Singh { 60*40863f4dSKP Singh EVP_PKEY *private_key = NULL; 61*40863f4dSKP Singh BIO *b; 62*40863f4dSKP Singh 63*40863f4dSKP Singh b = BIO_new_file(pkey_path, "rb"); 64*40863f4dSKP Singh private_key = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL); 65*40863f4dSKP Singh BIO_free(b); 66*40863f4dSKP Singh DISPLAY_OSSL_ERR(!private_key); 67*40863f4dSKP Singh return private_key; 68*40863f4dSKP Singh } 69*40863f4dSKP Singh 70*40863f4dSKP Singh static X509 *read_x509(const char *x509_name) 71*40863f4dSKP Singh { 72*40863f4dSKP Singh unsigned char buf[2]; 73*40863f4dSKP Singh X509 *x509 = NULL; 74*40863f4dSKP Singh BIO *b; 75*40863f4dSKP Singh int n; 76*40863f4dSKP Singh 77*40863f4dSKP Singh b = BIO_new_file(x509_name, "rb"); 78*40863f4dSKP Singh if (!b) 79*40863f4dSKP Singh goto cleanup; 80*40863f4dSKP Singh 81*40863f4dSKP Singh /* Look at the first two bytes of the file to determine the encoding */ 82*40863f4dSKP Singh n = BIO_read(b, buf, 2); 83*40863f4dSKP Singh if (n != 2) 84*40863f4dSKP Singh goto cleanup; 85*40863f4dSKP Singh 86*40863f4dSKP Singh if (BIO_reset(b) != 0) 87*40863f4dSKP Singh goto cleanup; 88*40863f4dSKP Singh 89*40863f4dSKP Singh if (buf[0] == 0x30 && buf[1] >= 0x81 && buf[1] <= 0x84) 90*40863f4dSKP Singh /* Assume raw DER encoded X.509 */ 91*40863f4dSKP Singh x509 = d2i_X509_bio(b, NULL); 92*40863f4dSKP Singh else 93*40863f4dSKP Singh /* Assume PEM encoded X.509 */ 94*40863f4dSKP Singh x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); 95*40863f4dSKP Singh 96*40863f4dSKP Singh cleanup: 97*40863f4dSKP Singh BIO_free(b); 98*40863f4dSKP Singh DISPLAY_OSSL_ERR(!x509); 99*40863f4dSKP Singh return x509; 100*40863f4dSKP Singh } 101*40863f4dSKP Singh 102*40863f4dSKP Singh __u32 register_session_key(const char *key_der_path) 103*40863f4dSKP Singh { 104*40863f4dSKP Singh unsigned char *der_buf = NULL; 105*40863f4dSKP Singh X509 *x509 = NULL; 106*40863f4dSKP Singh int key_id = -1; 107*40863f4dSKP Singh int der_len; 108*40863f4dSKP Singh 109*40863f4dSKP Singh if (!key_der_path) 110*40863f4dSKP Singh return key_id; 111*40863f4dSKP Singh x509 = read_x509(key_der_path); 112*40863f4dSKP Singh if (!x509) 113*40863f4dSKP Singh goto cleanup; 114*40863f4dSKP Singh der_len = i2d_X509(x509, &der_buf); 115*40863f4dSKP Singh if (der_len < 0) 116*40863f4dSKP Singh goto cleanup; 117*40863f4dSKP Singh key_id = syscall(__NR_add_key, "asymmetric", key_der_path, der_buf, 118*40863f4dSKP Singh (size_t)der_len, KEY_SPEC_SESSION_KEYRING); 119*40863f4dSKP Singh cleanup: 120*40863f4dSKP Singh X509_free(x509); 121*40863f4dSKP Singh OPENSSL_free(der_buf); 122*40863f4dSKP Singh DISPLAY_OSSL_ERR(key_id == -1); 123*40863f4dSKP Singh return key_id; 124*40863f4dSKP Singh } 125*40863f4dSKP Singh 126*40863f4dSKP Singh int bpftool_prog_sign(struct bpf_load_and_run_opts *opts) 127*40863f4dSKP Singh { 128*40863f4dSKP Singh BIO *bd_in = NULL, *bd_out = NULL; 129*40863f4dSKP Singh EVP_PKEY *private_key = NULL; 130*40863f4dSKP Singh CMS_ContentInfo *cms = NULL; 131*40863f4dSKP Singh long actual_sig_len = 0; 132*40863f4dSKP Singh X509 *x509 = NULL; 133*40863f4dSKP Singh int err = 0; 134*40863f4dSKP Singh 135*40863f4dSKP Singh bd_in = BIO_new_mem_buf(opts->insns, opts->insns_sz); 136*40863f4dSKP Singh if (!bd_in) { 137*40863f4dSKP Singh err = -ENOMEM; 138*40863f4dSKP Singh goto cleanup; 139*40863f4dSKP Singh } 140*40863f4dSKP Singh 141*40863f4dSKP Singh private_key = read_private_key(private_key_path); 142*40863f4dSKP Singh if (!private_key) { 143*40863f4dSKP Singh err = -EINVAL; 144*40863f4dSKP Singh goto cleanup; 145*40863f4dSKP Singh } 146*40863f4dSKP Singh 147*40863f4dSKP Singh x509 = read_x509(cert_path); 148*40863f4dSKP Singh if (!x509) { 149*40863f4dSKP Singh err = -EINVAL; 150*40863f4dSKP Singh goto cleanup; 151*40863f4dSKP Singh } 152*40863f4dSKP Singh 153*40863f4dSKP Singh cms = CMS_sign(NULL, NULL, NULL, NULL, 154*40863f4dSKP Singh CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | 155*40863f4dSKP Singh CMS_STREAM); 156*40863f4dSKP Singh if (!cms) { 157*40863f4dSKP Singh err = -EINVAL; 158*40863f4dSKP Singh goto cleanup; 159*40863f4dSKP Singh } 160*40863f4dSKP Singh 161*40863f4dSKP Singh if (!CMS_add1_signer(cms, x509, private_key, EVP_sha256(), 162*40863f4dSKP Singh CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP | 163*40863f4dSKP Singh CMS_USE_KEYID | CMS_NOATTR)) { 164*40863f4dSKP Singh err = -EINVAL; 165*40863f4dSKP Singh goto cleanup; 166*40863f4dSKP Singh } 167*40863f4dSKP Singh 168*40863f4dSKP Singh if (CMS_final(cms, bd_in, NULL, CMS_NOCERTS | CMS_BINARY) != 1) { 169*40863f4dSKP Singh err = -EIO; 170*40863f4dSKP Singh goto cleanup; 171*40863f4dSKP Singh } 172*40863f4dSKP Singh 173*40863f4dSKP Singh EVP_Digest(opts->insns, opts->insns_sz, opts->excl_prog_hash, 174*40863f4dSKP Singh &opts->excl_prog_hash_sz, EVP_sha256(), NULL); 175*40863f4dSKP Singh 176*40863f4dSKP Singh bd_out = BIO_new(BIO_s_mem()); 177*40863f4dSKP Singh if (!bd_out) { 178*40863f4dSKP Singh err = -ENOMEM; 179*40863f4dSKP Singh goto cleanup; 180*40863f4dSKP Singh } 181*40863f4dSKP Singh 182*40863f4dSKP Singh if (!i2d_CMS_bio_stream(bd_out, cms, NULL, 0)) { 183*40863f4dSKP Singh err = -EIO; 184*40863f4dSKP Singh goto cleanup; 185*40863f4dSKP Singh } 186*40863f4dSKP Singh 187*40863f4dSKP Singh actual_sig_len = BIO_get_mem_data(bd_out, NULL); 188*40863f4dSKP Singh if (actual_sig_len <= 0) { 189*40863f4dSKP Singh err = -EIO; 190*40863f4dSKP Singh goto cleanup; 191*40863f4dSKP Singh } 192*40863f4dSKP Singh 193*40863f4dSKP Singh if ((size_t)actual_sig_len > opts->signature_sz) { 194*40863f4dSKP Singh err = -ENOSPC; 195*40863f4dSKP Singh goto cleanup; 196*40863f4dSKP Singh } 197*40863f4dSKP Singh 198*40863f4dSKP Singh if (BIO_read(bd_out, opts->signature, actual_sig_len) != actual_sig_len) { 199*40863f4dSKP Singh err = -EIO; 200*40863f4dSKP Singh goto cleanup; 201*40863f4dSKP Singh } 202*40863f4dSKP Singh 203*40863f4dSKP Singh opts->signature_sz = actual_sig_len; 204*40863f4dSKP Singh cleanup: 205*40863f4dSKP Singh BIO_free(bd_out); 206*40863f4dSKP Singh CMS_ContentInfo_free(cms); 207*40863f4dSKP Singh X509_free(x509); 208*40863f4dSKP Singh EVP_PKEY_free(private_key); 209*40863f4dSKP Singh BIO_free(bd_in); 210*40863f4dSKP Singh DISPLAY_OSSL_ERR(err < 0); 211*40863f4dSKP Singh return err; 212*40863f4dSKP Singh } 213