tpm2_convert.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <strings.h>
  7. #include <openssl/bio.h>
  8. #include <openssl/err.h>
  9. #include <openssl/evp.h>
  10. #include <openssl/pem.h>
  11. #include "files.h"
  12. #include "log.h"
  13. #include "tpm2_alg_util.h"
  14. #include "tpm2_convert.h"
  15. #include "tpm2_openssl.h"
  16. static bool tpm2_convert_pubkey_ssl(TPMT_PUBLIC *public,
  17. tpm2_convert_pubkey_fmt format, const char *path);
  18. tpm2_convert_pubkey_fmt tpm2_convert_pubkey_fmt_from_optarg(const char *label) {
  19. if (strcasecmp(label, "der") == 0) {
  20. return pubkey_format_der;
  21. } else if (strcasecmp(label, "pem") == 0) {
  22. return pubkey_format_pem;
  23. } else if (strcasecmp(label, "tss") == 0) {
  24. return pubkey_format_tss;
  25. } else if (strcasecmp(label, "tpmt") == 0) {
  26. return pubkey_format_tpmt;
  27. }
  28. LOG_ERR("Invalid public key output format '%s' specified", label);
  29. return pubkey_format_err;
  30. }
  31. tpm2_convert_sig_fmt tpm2_convert_sig_fmt_from_optarg(const char *label) {
  32. if (strcasecmp(label, "tss") == 0) {
  33. return signature_format_tss;
  34. } else if (strcasecmp(label, "plain") == 0) {
  35. return signature_format_plain;
  36. }
  37. LOG_ERR("Invalid signature output format '%s' specified", label);
  38. return signature_format_err;
  39. }
  40. static void print_ssl_error(const char *failed_action) {
  41. char errstr[256] = { 0 };
  42. unsigned long errnum = ERR_get_error();
  43. ERR_error_string_n(errnum, errstr, sizeof(errstr));
  44. LOG_ERR("%s: %s", failed_action, errstr);
  45. }
  46. bool tpm2_convert_pubkey_save(TPM2B_PUBLIC *public,
  47. tpm2_convert_pubkey_fmt format, const char *path) {
  48. if (format == pubkey_format_der || format == pubkey_format_pem) {
  49. return tpm2_convert_pubkey_ssl(&public->publicArea, format, path);
  50. } else if (format == pubkey_format_tss) {
  51. return files_save_public(public, path);
  52. } else if (format == pubkey_format_tpmt) {
  53. return files_save_template(&public->publicArea, path);
  54. }
  55. LOG_ERR("Unsupported public key output format.");
  56. return false;
  57. }
  58. static bool convert_pubkey_RSA(TPMT_PUBLIC *public,
  59. tpm2_convert_pubkey_fmt format, BIO *bio) {
  60. bool ret = false;
  61. RSA *ssl_rsa_key = NULL;
  62. BIGNUM *e = NULL, *n = NULL;
  63. UINT32 exponent = (public->parameters).rsaDetail.exponent;
  64. if (exponent == 0) {
  65. exponent = 0x10001;
  66. }
  67. // OpenSSL expects this in network byte order
  68. exponent = tpm2_util_hton_32(exponent);
  69. ssl_rsa_key = RSA_new();
  70. if (!ssl_rsa_key) {
  71. print_ssl_error("Failed to allocate OpenSSL RSA structure");
  72. goto error;
  73. }
  74. e = BN_bin2bn((void*) &exponent, sizeof(exponent), NULL);
  75. n = BN_bin2bn(public->unique.rsa.buffer, public->unique.rsa.size,
  76. NULL);
  77. if (!n || !e) {
  78. print_ssl_error("Failed to convert data to SSL internal format");
  79. goto error;
  80. }
  81. if (!RSA_set0_key(ssl_rsa_key, n, e, NULL)) {
  82. print_ssl_error("Failed to set RSA modulus and exponent components");
  83. goto error;
  84. }
  85. /* modulus and exponent components are now owned by the RSA struct */
  86. n = e = NULL;
  87. int ssl_res = 0;
  88. switch (format) {
  89. case pubkey_format_pem:
  90. ssl_res = PEM_write_bio_RSA_PUBKEY(bio, ssl_rsa_key);
  91. break;
  92. case pubkey_format_der:
  93. ssl_res = i2d_RSA_PUBKEY_bio(bio, ssl_rsa_key);
  94. break;
  95. default:
  96. LOG_ERR("Invalid OpenSSL target format %d encountered", format);
  97. goto error;
  98. }
  99. if (ssl_res <= 0) {
  100. print_ssl_error("OpenSSL public key conversion failed");
  101. goto error;
  102. }
  103. ret = true;
  104. error: if (n) {
  105. BN_free(n);
  106. }
  107. if (e) {
  108. BN_free(e);
  109. }
  110. if (ssl_rsa_key) {
  111. RSA_free(ssl_rsa_key);
  112. }
  113. return ret;
  114. }
  115. static bool convert_pubkey_ECC(TPMT_PUBLIC *public,
  116. tpm2_convert_pubkey_fmt format, BIO *bio) {
  117. BIGNUM *x = NULL;
  118. BIGNUM *y = NULL;
  119. EC_KEY *key = NULL;
  120. EC_POINT *point = NULL;
  121. const EC_GROUP *group = NULL;
  122. bool result = false;
  123. TPMS_ECC_PARMS *tpm_ecc = &public->parameters.eccDetail;
  124. TPMS_ECC_POINT *tpm_point = &public->unique.ecc;
  125. int nid = tpm2_ossl_curve_to_nid(tpm_ecc->curveID);
  126. if (nid < 0) {
  127. return false;
  128. }
  129. /*
  130. * Create an empty EC key by the NID
  131. */
  132. key = EC_KEY_new_by_curve_name(nid);
  133. if (!key) {
  134. print_ssl_error("Failed to create EC key from nid");
  135. return false;
  136. }
  137. group = EC_KEY_get0_group(key);
  138. if (!group) {
  139. print_ssl_error("EC key missing group");
  140. goto out;
  141. }
  142. /*
  143. * Create a new point in the group, which is the public key.
  144. */
  145. point = EC_POINT_new(group);
  146. /*
  147. * Set the affine coordinates for the point
  148. */
  149. x = BN_bin2bn(tpm_point->x.buffer, tpm_point->x.size, NULL);
  150. if (!x) {
  151. print_ssl_error("Could not convert x coordinate to BN");
  152. goto out;
  153. }
  154. y = BN_bin2bn(tpm_point->y.buffer, tpm_point->y.size, NULL);
  155. if (!y) {
  156. print_ssl_error("Could not convert y coordinate to BN");
  157. goto out;
  158. }
  159. int rc = EC_POINT_set_affine_coordinates_tss(group, point, x, y, NULL);
  160. if (!rc) {
  161. print_ssl_error("Could not set affine coordinates");
  162. goto out;
  163. }
  164. rc = EC_KEY_set_public_key(key, point);
  165. if (!rc) {
  166. print_ssl_error("Could not set point as public key portion");
  167. goto out;
  168. }
  169. int ssl_res = 0;
  170. switch (format) {
  171. case pubkey_format_pem:
  172. ssl_res = PEM_write_bio_EC_PUBKEY(bio, key);
  173. break;
  174. case pubkey_format_der:
  175. ssl_res = i2d_EC_PUBKEY_bio(bio, key);
  176. break;
  177. default:
  178. LOG_ERR("Invalid OpenSSL target format %d encountered", format);
  179. goto out;
  180. }
  181. if (ssl_res <= 0) {
  182. print_ssl_error("OpenSSL public key conversion failed");
  183. goto out;
  184. }
  185. result = true;
  186. out:
  187. if (x) {
  188. BN_free(x);
  189. }
  190. if (y) {
  191. BN_free(y);
  192. }
  193. if (point) {
  194. EC_POINT_free(point);
  195. }
  196. if (key) {
  197. EC_KEY_free(key);
  198. }
  199. return result;
  200. }
  201. static bool tpm2_convert_pubkey_bio(TPMT_PUBLIC *public,
  202. tpm2_convert_pubkey_fmt format, BIO *bio) {
  203. bool result = false;
  204. switch (public->type) {
  205. case TPM2_ALG_RSA:
  206. result = convert_pubkey_RSA(public, format, bio);
  207. break;
  208. case TPM2_ALG_ECC:
  209. result = convert_pubkey_ECC(public, format, bio);
  210. break;
  211. default:
  212. LOG_ERR(
  213. "Unsupported key type for requested output format. Only RSA is supported.");
  214. }
  215. ERR_free_strings();
  216. return result;
  217. }
  218. static bool tpm2_convert_pubkey_ssl(TPMT_PUBLIC *public,
  219. tpm2_convert_pubkey_fmt format, const char *path) {
  220. BIO *bio = BIO_new_file(path, "wb");
  221. if (!bio) {
  222. LOG_ERR("Failed to open public key output file '%s': %s", path,
  223. ERR_error_string(ERR_get_error(), NULL));
  224. return false;
  225. }
  226. bool result = tpm2_convert_pubkey_bio(public, format, bio);
  227. BIO_free(bio);
  228. return result;
  229. }
  230. bool tpm2_convert_sig_save(TPMT_SIGNATURE *signature,
  231. tpm2_convert_sig_fmt format, const char *path) {
  232. switch (format) {
  233. case signature_format_tss:
  234. return files_save_signature(signature, path);
  235. case signature_format_plain: {
  236. UINT8 *buffer;
  237. UINT16 size;
  238. buffer = tpm2_convert_sig(&size, signature);
  239. if (buffer == NULL) {
  240. return false;
  241. }
  242. bool ret = files_save_bytes_to_file(path, buffer, size);
  243. free(buffer);
  244. return ret;
  245. }
  246. default:
  247. LOG_ERR("Unsupported signature output format.");
  248. return false;
  249. }
  250. }
  251. /**
  252. * Parses the ASN1 format for an ECDSA Signature
  253. *
  254. * The ASN1 format for ECDSA signature is: https://www.ietf.org/rfc/rfc5480.txt
  255. * ECDSA-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER }
  256. *
  257. * @param path
  258. * @param ecdsa
  259. * @return
  260. */
  261. static bool pop_ecdsa(const char *path, TPMS_SIGNATURE_ECDSA *ecdsa) {
  262. TPM2B_MAX_BUFFER buf = { .size = sizeof(buf.buffer) };
  263. bool res = files_load_bytes_from_path(path, buf.buffer, &buf.size);
  264. if (!res) {
  265. return res;
  266. }
  267. int tag;
  268. int class;
  269. long len;
  270. const unsigned char *p = buf.buffer;
  271. int j = ASN1_get_object(&p, &len, &tag, &class, buf.size);
  272. if (!(j & V_ASN1_CONSTRUCTED)) {
  273. LOG_ERR("Expected ECDSA signature to start as ASN1 Constructed object");
  274. return false;
  275. }
  276. if (tag != V_ASN1_SEQUENCE) {
  277. LOG_ERR("Expected ECDSA signature to be an ASN1 sequence");
  278. return false;
  279. }
  280. /*
  281. * Get R
  282. */
  283. TPM2B_ECC_PARAMETER *R = &ecdsa->signatureR;
  284. ASN1_INTEGER *r = d2i_ASN1_INTEGER(NULL, &p, len);
  285. if (!r) {
  286. LOG_ERR("oom");
  287. return false;
  288. }
  289. memcpy(R->buffer, r->data, r->length);
  290. R->size = r->length;
  291. ASN1_INTEGER_free(r);
  292. /*
  293. * Get S
  294. */
  295. TPM2B_ECC_PARAMETER *S = &ecdsa->signatureS;
  296. ASN1_INTEGER *s = d2i_ASN1_INTEGER(NULL, &p, len);
  297. if (!s) {
  298. LOG_ERR("oom");
  299. return false;
  300. }
  301. memcpy(S->buffer, s->data, s->length);
  302. S->size = s->length;
  303. ASN1_INTEGER_free(s);
  304. return true;
  305. }
  306. static bool sig_load(const char *path, TPMI_ALG_SIG_SCHEME sig_alg,
  307. TPMI_ALG_HASH halg, TPMT_SIGNATURE *signature) {
  308. signature->sigAlg = sig_alg;
  309. bool res = false;
  310. switch (sig_alg) {
  311. case TPM2_ALG_RSASSA:
  312. signature->signature.rsassa.hash = halg;
  313. signature->signature.rsassa.sig.size =
  314. sizeof(signature->signature.rsassa.sig.buffer);
  315. res = files_load_bytes_from_path(path,
  316. signature->signature.rsassa.sig.buffer,
  317. &signature->signature.rsassa.sig.size);
  318. return res;
  319. case TPM2_ALG_RSAPSS:
  320. signature->signature.rsapss.hash = halg;
  321. signature->signature.rsapss.sig.size =
  322. sizeof(signature->signature.rsapss.sig.buffer);
  323. res = files_load_bytes_from_path(path,
  324. signature->signature.rsapss.sig.buffer,
  325. &signature->signature.rsapss.sig.size);
  326. return res;
  327. case TPM2_ALG_ECDSA:
  328. signature->signature.ecdsa.hash = halg;
  329. return pop_ecdsa(path, &signature->signature.ecdsa);
  330. default:
  331. LOG_ERR("Unsupported signature input format.");
  332. return false;
  333. }
  334. }
  335. bool tpm2_convert_sig_load(const char *path, tpm2_convert_sig_fmt format,
  336. TPMI_ALG_SIG_SCHEME sig_alg, TPMI_ALG_HASH halg,
  337. TPMT_SIGNATURE *signature) {
  338. switch (format) {
  339. case signature_format_tss:
  340. return files_load_signature(path, signature);
  341. case signature_format_plain:
  342. return sig_load(path, sig_alg, halg, signature);
  343. default:
  344. LOG_ERR("Unsupported signature input format.");
  345. return false;
  346. }
  347. }
  348. bool tpm2_convert_sig_load_plain(const char *path,
  349. TPM2B_MAX_BUFFER *signature, TPMI_ALG_HASH *halg) {
  350. /*
  351. * TSS signature need be read and converted to plain
  352. *
  353. * So load it up into the TPMT Structure
  354. */
  355. TPMT_SIGNATURE tmp = { 0 };
  356. bool ret = files_load_signature_silent(path, &tmp);
  357. if (!ret) {
  358. /* plain signatures are just used as is */
  359. *halg = TPM2_ALG_NULL;
  360. signature->size = sizeof(signature->buffer);
  361. return files_load_bytes_from_path(path,
  362. signature->buffer,
  363. &signature->size);
  364. }
  365. *halg = tmp.signature.any.hashAlg;
  366. /* Then convert it to plain, but into a buffer */
  367. UINT8 *buffer;
  368. UINT16 size;
  369. buffer = tpm2_convert_sig(&size, &tmp);
  370. if (buffer == NULL) {
  371. return false;
  372. }
  373. if (size > sizeof(signature->buffer)) {
  374. LOG_ERR("Signature size bigger than buffer, got: %u expected"
  375. " less than %zu", size, sizeof(signature->buffer));
  376. free(buffer);
  377. return false;
  378. }
  379. signature->size = size;
  380. memcpy(signature->buffer, buffer, size);
  381. free(buffer);
  382. return true;
  383. }
  384. static UINT8 *extract_ecdsa(TPMS_SIGNATURE_ECDSA *ecdsa, UINT16 *size) {
  385. /* the DER encoded ECDSA signature */
  386. unsigned char *buf = NULL;
  387. TPM2B_ECC_PARAMETER *R = &ecdsa->signatureR;
  388. TPM2B_ECC_PARAMETER *S = &ecdsa->signatureS;
  389. ECDSA_SIG *sig = ECDSA_SIG_new();
  390. if (sig == NULL) {
  391. return NULL;
  392. }
  393. BIGNUM *bn_r = BN_bin2bn(R->buffer, R->size, NULL);
  394. if (!bn_r) {
  395. goto out;
  396. }
  397. BIGNUM *bn_s = BN_bin2bn(S->buffer, S->size, NULL);
  398. if (!bn_s) {
  399. BN_free(bn_r);
  400. goto out;
  401. }
  402. int rc = ECDSA_SIG_set0(sig, bn_r, bn_s);
  403. if (rc != 1) {
  404. BN_free(bn_r);
  405. BN_free(bn_s);
  406. goto out;
  407. }
  408. /*
  409. * r and s are now owned by the ecdsa signature no need
  410. * to free
  411. */
  412. int len = i2d_ECDSA_SIG(sig, NULL);
  413. if (len <= 0) {
  414. goto out;
  415. }
  416. buf = malloc(len);
  417. if (!buf) {
  418. goto out;
  419. }
  420. unsigned char *pp = buf;
  421. len = i2d_ECDSA_SIG(sig, &pp);
  422. if (len <= 0) {
  423. free(buf);
  424. buf = NULL;
  425. goto out;
  426. }
  427. *size = len;
  428. /* success */
  429. out:
  430. ECDSA_SIG_free(sig);
  431. return buf;
  432. }
  433. UINT8 *tpm2_convert_sig(UINT16 *size, TPMT_SIGNATURE *signature) {
  434. UINT8 *buffer = NULL;
  435. *size = 0;
  436. switch (signature->sigAlg) {
  437. case TPM2_ALG_RSASSA:
  438. *size = signature->signature.rsassa.sig.size;
  439. buffer = malloc(*size);
  440. if (!buffer) {
  441. goto nomem;
  442. }
  443. memcpy(buffer, signature->signature.rsassa.sig.buffer, *size);
  444. break;
  445. case TPM2_ALG_RSAPSS:
  446. *size = signature->signature.rsapss.sig.size;
  447. buffer = malloc(*size);
  448. if (!buffer) {
  449. goto nomem;
  450. }
  451. memcpy(buffer, signature->signature.rsapss.sig.buffer, *size);
  452. break;
  453. case TPM2_ALG_HMAC: {
  454. TPMU_HA *hmac_sig = &(signature->signature.hmac.digest);
  455. *size = tpm2_alg_util_get_hash_size(signature->signature.hmac.hashAlg);
  456. if (*size == 0) {
  457. LOG_ERR("Hash algorithm %d has 0 size",
  458. signature->signature.hmac.hashAlg);
  459. goto nomem;
  460. }
  461. buffer = malloc(*size);
  462. if (!buffer) {
  463. goto nomem;
  464. }
  465. memcpy(buffer, hmac_sig, *size);
  466. break;
  467. }
  468. case TPM2_ALG_ECDSA: {
  469. return extract_ecdsa(&signature->signature.ecdsa, size);
  470. }
  471. default:
  472. LOG_ERR("%s: unknown signature scheme: 0x%x", __func__,
  473. signature->sigAlg);
  474. return NULL;
  475. }
  476. return buffer;
  477. nomem:
  478. LOG_ERR("%s: couldn't allocate memory", __func__);
  479. return NULL;
  480. }
  481. bool tpm2_public_load_pkey(const char *path, EVP_PKEY **pkey) {
  482. bool result = false;
  483. BIO *bio = NULL;
  484. EVP_PKEY *p = NULL;
  485. /*
  486. * Order Matters. You must check for the smallest TSS size first, which
  487. * it the TPMT_PUBLIC as it's embedded in the TPM2B_PUBLIC. It's possible
  488. * to have valid TPMT's and have them parse as valid TPM2B_PUBLIC's (apparantly).
  489. *
  490. * If none of them convert, we try it as a plain signature.
  491. */
  492. TPM2B_PUBLIC public = { 0 };
  493. bool ret = files_load_template_silent(path, &public.publicArea);
  494. if (ret) {
  495. goto convert_to_pem;
  496. }
  497. ret = files_load_public_silent(path, &public);
  498. if (ret) {
  499. goto convert_to_pem;
  500. }
  501. /* not a tss format, just treat it as a pem file */
  502. bio = BIO_new_file(path, "rb");
  503. if (!bio) {
  504. LOG_ERR("Failed to open public key output file '%s': %s", path,
  505. ERR_error_string(ERR_get_error(), NULL));
  506. return false;
  507. }
  508. /* not a tpm data structure, must be pem */
  509. goto try_pem;
  510. convert_to_pem:
  511. bio = BIO_new(BIO_s_mem());
  512. if (!bio) {
  513. LOG_ERR("Failed to allocate memory bio: %s",
  514. ERR_error_string(ERR_get_error(), NULL));
  515. return false;
  516. }
  517. ret = tpm2_convert_pubkey_bio(&public.publicArea, pubkey_format_pem, bio);
  518. if (!ret) {
  519. goto out;
  520. }
  521. try_pem:
  522. p = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
  523. if (!p) {
  524. LOG_ERR("Failed to convert public key from file '%s': %s", path,
  525. ERR_error_string(ERR_get_error(), NULL));
  526. goto out;
  527. }
  528. *pkey = p;
  529. result = true;
  530. out:
  531. if (bio) {
  532. BIO_free(bio);
  533. }
  534. return result;
  535. }
  536. bool tpm2_base64_encode(BYTE *buffer, size_t buffer_length, char *base64) {
  537. unsigned char out[1024];
  538. int outl;
  539. EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
  540. EVP_EncodeInit(ctx);
  541. #if defined(LIB_TPM2_OPENSSL_OPENSSL_PRE11)
  542. EVP_EncodeUpdate(ctx, out, &outl, buffer, buffer_length);
  543. #else
  544. int rc = EVP_EncodeUpdate(ctx, out, &outl, buffer, buffer_length);
  545. if(rc < 0) {
  546. LOG_ERR("EVP_DecodeUpdate failed with %d\n", rc);
  547. EVP_ENCODE_CTX_free(ctx);
  548. return false;
  549. }
  550. #endif
  551. EVP_EncodeFinal(ctx, out, &outl); // no return value
  552. EVP_ENCODE_CTX_free(ctx);
  553. strcpy(base64, (char*) out);
  554. return true;
  555. }
  556. bool tpm2_base64_decode(char *base64, BYTE *buffer, size_t *buffer_length) {
  557. bool is_base64_bufferlen_valid = strlen(base64) > 1024 ? false : true;
  558. if (!is_base64_bufferlen_valid) {
  559. return false;
  560. }
  561. unsigned char base64u[1024];
  562. memcpy(base64u, base64, strlen(base64));
  563. EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
  564. EVP_DecodeInit(ctx);
  565. unsigned char out[1024];
  566. int outl;
  567. int rc = EVP_DecodeUpdate(ctx, out, &outl, base64u, strlen(base64));
  568. if(rc < 0) {
  569. LOG_ERR("EVP_DecodeUpdate failed with %d\n", rc);
  570. EVP_ENCODE_CTX_free(ctx);
  571. return false;
  572. }
  573. *buffer_length = outl;
  574. rc = EVP_DecodeFinal(ctx, out, &outl);
  575. if(rc < 0) {
  576. LOG_ERR("EVP_DecodeFinal failed with %d\n", rc);
  577. EVP_ENCODE_CTX_free(ctx);
  578. return false;
  579. }
  580. EVP_ENCODE_CTX_free(ctx);
  581. *buffer_length += outl;
  582. memcpy(buffer, out, *buffer_length);
  583. return true;
  584. }