summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSzymon Starzycki <sstar@google.com>2013-10-02 17:21:41 -0700
committerColin Cross <ccross@android.com>2013-12-04 15:00:52 -0800
commit4662a114a416e636de805fbd875f8b90fc5965b9 (patch)
treecd62973e812f8f2972893ba2ef4dc405192258c6
parent27ea99fb99153e3b2d45efd6fce9785538469e49 (diff)
downloadcore-4662a114a416e636de805fbd875f8b90fc5965b9.tar.gz
Revert "Revert "Fastbootd: flashing certification""
CMS functionality is now available This reverts commit 068b71dd9cd6cb03dfcdc0c9deced361780bc0d3. Conflicts: fastbootd/Android.mk fastbootd/fastbootd.c fastbootd/utils.c fastbootd/utils.h Change-Id: I1a27459b41d9297603deb124c65f237ff971e5b6
-rw-r--r--fastbootd/Android.mk3
-rw-r--r--fastbootd/commands.c39
-rw-r--r--fastbootd/commands/flash.c47
-rw-r--r--fastbootd/commands/flash.h2
-rw-r--r--fastbootd/fastbootd.c2
-rw-r--r--fastbootd/other/sign/src/SignImg.java181
-rw-r--r--fastbootd/secure.c166
-rw-r--r--fastbootd/secure.h53
8 files changed, 485 insertions, 8 deletions
diff --git a/fastbootd/Android.mk b/fastbootd/Android.mk
index c051721c8..0f32dbfcb 100644
--- a/fastbootd/Android.mk
+++ b/fastbootd/Android.mk
@@ -33,6 +33,7 @@ LOCAL_SRC_FILES := \
protocol.c \
network_discovery.c \
socket_client.c \
+ secure.c \
transport.c \
transport_socket.c \
trigger.c \
@@ -41,7 +42,7 @@ LOCAL_SRC_FILES := \
LOCAL_MODULE := fastbootd
LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter -DFLASH_CERT
LOCAL_LDFLAGS := -ldl
LOCAL_SHARED_LIBRARIES := \
diff --git a/fastbootd/commands.c b/fastbootd/commands.c
index 83e86b05d..2f6e86a76 100644
--- a/fastbootd/commands.c
+++ b/fastbootd/commands.c
@@ -52,6 +52,8 @@
static void cmd_boot(struct protocol_handle *phandle, const char *arg)
{
+ int sz, atags_sz, new_atags_sz;
+ int rv;
unsigned kernel_actual;
unsigned ramdisk_actual;
unsigned second_actual;
@@ -59,9 +61,11 @@ static void cmd_boot(struct protocol_handle *phandle, const char *arg)
void *ramdisk_ptr;
void *second_ptr;
struct boot_img_hdr *hdr;
- int sz, atags_sz, new_atags_sz;
- int rv;
- char *ptr = NULL, *atags_ptr = NULL, *new_atags = NULL;
+ char *ptr = NULL;
+ char *atags_ptr = NULL;
+ char *new_atags = NULL;
+ int data_fd = 0;
+
D(DEBUG, "cmd_boot %s\n", arg);
if (phandle->download_fd < 0) {
@@ -75,9 +79,18 @@ static void cmd_boot(struct protocol_handle *phandle, const char *arg)
goto error;
}
- sz = get_file_size(phandle->download_fd);
+ // TODO: With cms we can also verify partition name included as
+ // cms signed attribute
+ if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) {
+ fastboot_fail(phandle, "Access forbiden you need the certificate");
+ return;
+ }
+
+ sz = get_file_size(data_fd);
+
ptr = (char *) mmap(NULL, sz, PROT_READ,
- MAP_POPULATE | MAP_PRIVATE, phandle->download_fd, 0);
+ MAP_POPULATE | MAP_PRIVATE, data_fd, 0);
+
hdr = (struct boot_img_hdr *) ptr;
if (ptr == MAP_FAILED) {
@@ -130,6 +143,7 @@ static void cmd_boot(struct protocol_handle *phandle, const char *arg)
free(atags_ptr);
munmap(ptr, sz);
free(new_atags);
+ close(data_fd);
D(INFO, "Kexec going to reboot");
reboot(LINUX_REBOOT_CMD_KEXEC);
@@ -256,6 +270,7 @@ static void cmd_flash(struct protocol_handle *phandle, const char *arg)
char data[BOOT_MAGIC_SIZE];
char path[PATH_MAX];
ssize_t header_sz = 0;
+ int data_fd = 0;
D(DEBUG, "cmd_flash %s\n", arg);
@@ -273,9 +288,14 @@ static void cmd_flash(struct protocol_handle *phandle, const char *arg)
return;
}
+ if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) {
+ fastboot_fail(phandle, "Access forbiden you need certificate");
+ return;
+ }
+
// TODO: Maybe its goot idea to check whether the partition is just bootable partition
if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
- if (read_data_once(phandle->download_fd, data, BOOT_MAGIC_SIZE) < BOOT_MAGIC_SIZE) {
+ if (read_data_once(data_fd, data, BOOT_MAGIC_SIZE) < BOOT_MAGIC_SIZE) {
fastboot_fail(phandle, "incoming data read error, cannot read boot header");
return;
}
@@ -287,7 +307,10 @@ static void cmd_flash(struct protocol_handle *phandle, const char *arg)
partition = flash_get_partiton(path);
- sz = get_file_size64(phandle->download_fd);
+ sz = get_file_size64(data_fd);
+
+ sz -= header_sz;
+
if (sz > get_file_size64(partition)) {
flash_close(partition);
D(WARN, "size of file too large");
@@ -304,6 +327,8 @@ static void cmd_flash(struct protocol_handle *phandle, const char *arg)
D(INFO, "partition '%s' updated\n", arg);
flash_close(partition);
+ close(data_fd);
+ //TODO: check who is closing phandle->download_fd
fastboot_okay(phandle, "");
}
diff --git a/fastbootd/commands/flash.c b/fastbootd/commands/flash.c
index 5f8b9313f..0954217b5 100644
--- a/fastbootd/commands/flash.c
+++ b/fastbootd/commands/flash.c
@@ -39,6 +39,9 @@
#include "utils.h"
#include "commands/partitions.h"
+#ifdef FLASH_CERT
+#include "secure.h"
+#endif
#define ALLOWED_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."
#define BUFFER_SIZE 1024 * 1024
@@ -112,3 +115,47 @@ int flash_write(int partition_fd, int data_fd, ssize_t size, ssize_t skip)
return 0;
}
+
+#ifdef FLASH_CERT
+
+int flash_validate_certificate(int signed_fd, int *data_fd) {
+ int ret = 0;
+ const char *cert_path;
+ X509_STORE *store = NULL;
+ CMS_ContentInfo *content_info;
+ BIO *content;
+
+ cert_path = fastboot_getvar("certificate-path");
+ if (!strcmp(cert_path, "")) {
+ D(ERR, "could not find cert-key value in config file");
+ goto finish;
+ }
+
+ store = cert_store_from_path(cert_path);
+ if (store == NULL) {
+ D(ERR, "unable to create certification store");
+ goto finish;
+ }
+
+ if (cert_read(signed_fd, &content_info, &content)) {
+ D(ERR, "reading data failed");
+ goto finish;
+ }
+
+ ret = cert_verify(content, content_info, store, data_fd);
+ cert_release(content, content_info);
+
+ return ret;
+
+finish:
+ if (store != NULL)
+ cert_release_store(store);
+
+ return ret;
+}
+
+#else
+int flash_validate_certificate(int signed_fd, int *data_fd) {
+ return 1;
+}
+#endif
diff --git a/fastbootd/commands/flash.h b/fastbootd/commands/flash.h
index 8ffd688c2..86dc8117e 100644
--- a/fastbootd/commands/flash.h
+++ b/fastbootd/commands/flash.h
@@ -58,5 +58,7 @@ static inline ssize_t read_data_once(int fd, char *buffer, ssize_t size) {
return readcount;
}
+int flash_validate_certificate(int signed_fd, int *data_fd);
+
#endif
diff --git a/fastbootd/fastbootd.c b/fastbootd/fastbootd.c
index 085cbfa01..9318c9928 100644
--- a/fastbootd/fastbootd.c
+++ b/fastbootd/fastbootd.c
@@ -23,6 +23,7 @@
#include "debug.h"
#include "trigger.h"
#include "socket_client.h"
+#include "secure.h"
unsigned int debug_level = DEBUG;
@@ -72,6 +73,7 @@ int main(int argc, char **argv)
run_socket_client();
}
else {
+ cert_init_crypto();
config_init();
load_trigger();
commands_init();
diff --git a/fastbootd/other/sign/src/SignImg.java b/fastbootd/other/sign/src/SignImg.java
new file mode 100644
index 000000000..338d427fa
--- /dev/null
+++ b/fastbootd/other/sign/src/SignImg.java
@@ -0,0 +1,181 @@
+package signtool;
+
+import java.io.*;
+import java.util.Properties;
+import java.util.ArrayList;
+
+import javax.mail.internet.*;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.activation.MailcapCommandMap;
+import javax.activation.CommandMap;
+
+import java.security.PrivateKey;
+import java.security.Security;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateEncodingException;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.cms.CMSProcessableByteArray;
+import org.bouncycastle.cms.CMSSignedGenerator;
+import org.bouncycastle.cms.CMSSignedDataGenerator;
+import org.bouncycastle.cms.CMSSignedGenerator;
+import org.bouncycastle.cms.CMSProcessable;
+import org.bouncycastle.cms.CMSSignedData;
+import org.bouncycastle.cms.CMSTypedData;
+import org.bouncycastle.cert.jcajce.JcaCertStore;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.DEROutputStream;
+import org.bouncycastle.asn1.ASN1Object;
+
+
+public class SignImg {
+
+ /* It reads private key in pkcs#8 formate
+ * Conversion:
+ * openssl pkcs8 -topk8 -nocrypt -outform DER < inkey.pem > outkey.pk8
+ */
+ private static PrivateKey getPrivateKey(String path) throws IOException, FileNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException {
+ File file = new File(path);
+ FileInputStream fis = new FileInputStream(file);
+ byte[] data = new byte[(int)file.length()];
+ fis.read(data);
+ fis.close();
+
+ PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(data);
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ PrivateKey privateKey = kf.generatePrivate(kspec);
+
+ return privateKey;
+ }
+
+ private static MimeBodyPart getContent(String path) throws IOException, FileNotFoundException, MessagingException {
+ MimeBodyPart body = new MimeBodyPart();
+
+ File file = new File(path);
+ FileInputStream fis = new FileInputStream(file);
+ byte[] data = new byte[(int)file.length()];
+ fis.read(data);
+ fis.close();
+
+ body.setContent(data, "application/octet-stream");
+
+ return body;
+ }
+
+ private static CMSProcessableByteArray getCMSContent(String path) throws IOException, FileNotFoundException, MessagingException {
+ File file = new File(path);
+ FileInputStream fis = new FileInputStream(file);
+ byte[] data = new byte[(int)file.length()];
+ fis.read(data);
+ fis.close();
+ CMSProcessableByteArray cms = new CMSProcessableByteArray(data);
+
+ return cms;
+ }
+
+ private static X509Certificate readCert(String path) throws IOException, FileNotFoundException, CertificateException {
+ File file = new File(path);
+ FileInputStream is = new FileInputStream(file);
+
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ Certificate cert = cf.generateCertificate(is);
+ is.close();
+
+ return (X509Certificate) cert;
+ }
+
+ private static void save(MimeBodyPart content, String path) throws IOException, FileNotFoundException, MessagingException {
+ File file = new File(path);
+ FileOutputStream os = new FileOutputStream(file);
+
+ content.writeTo(os);
+
+ os.close();
+ }
+
+ private static Store certToStore(X509Certificate certificate) throws CertificateEncodingException {
+ ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
+ certList.add(certificate);
+ return new JcaCertStore(certList);
+ }
+
+ public static void setDefaultMailcap()
+ {
+ MailcapCommandMap _mailcap =
+ (MailcapCommandMap)CommandMap.getDefaultCommandMap();
+
+ _mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
+ _mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
+ _mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
+ _mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
+ _mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
+
+ CommandMap.setDefaultCommandMap(_mailcap);
+ }
+
+ public static void main(String[] args) {
+ try {
+ if (args.length < 4) {
+ System.out.println("Usage: signimg data private_key certificate output");
+ return;
+ }
+ System.out.println("Signing the image");
+ setDefaultMailcap();
+
+ Security.addProvider(new BouncyCastleProvider());
+
+ PrivateKey key = getPrivateKey(args[1]);
+ System.out.println("File read sucessfully");
+
+ CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
+
+ CMSTypedData body = getCMSContent(args[0]);
+ System.out.println("Content read sucessfully");
+
+ X509Certificate cert = (X509Certificate) readCert(args[2]);
+ System.out.println("Certificate read sucessfully");
+
+ ContentSigner sha256Signer = new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").build(key);
+
+ Store certs = certToStore(cert);
+
+ generator.addCertificates(certs);
+ generator.addSignerInfoGenerator(
+ new JcaSignerInfoGeneratorBuilder(
+ new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
+ .build(sha256Signer, cert));
+
+ CMSSignedData signed = generator.generate(body, true);
+ System.out.println("Signed");
+
+ Properties props = System.getProperties();
+ Session session = Session.getDefaultInstance(props, null);
+
+ File file = new File(args[3]);
+ FileOutputStream os = new FileOutputStream(file);
+
+ ASN1InputStream asn1 = new ASN1InputStream(signed.getEncoded());
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(os);
+ dOut.writeObject(ASN1Object.fromByteArray(signed.getEncoded()));
+
+ }
+ catch (Exception ex) {
+ System.out.println("Exception during programm execution: " + ex.getMessage());
+ }
+ }
+}
diff --git a/fastbootd/secure.c b/fastbootd/secure.c
new file mode 100644
index 000000000..75a6f3c25
--- /dev/null
+++ b/fastbootd/secure.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <openssl/pem.h>
+#include <openssl/engine.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+#include <openssl/cms.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "secure.h"
+#include "debug.h"
+#include "utils.h"
+
+
+void cert_init_crypto() {
+ CRYPTO_malloc_init();
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+ ENGINE_load_builtin_engines();
+}
+
+X509_STORE *cert_store_from_path(const char *path) {
+
+ X509_STORE *store;
+ struct stat st;
+ X509_LOOKUP *lookup;
+
+ if (stat(path, &st)) {
+ D(ERR, "Unable to stat cert path");
+ goto error;
+ }
+
+ if (!(store = X509_STORE_new())) {
+ goto error;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ lookup = X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
+ if (lookup == NULL)
+ goto error;
+ if (!X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) {
+ D(ERR, "Error loading cert directory %s", path);
+ goto error;
+ }
+ }
+ else if(S_ISREG(st.st_mode)) {
+ lookup = X509_STORE_add_lookup(store,X509_LOOKUP_file());
+ if (lookup == NULL)
+ goto error;
+ if (!X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM)) {
+ D(ERR, "Error loading cert directory %s", path);
+ goto error;
+ }
+ }
+ else {
+ D(ERR, "cert path is not directory or regular file");
+ goto error;
+ }
+
+ return store;
+
+error:
+ return NULL;
+}
+
+
+int cert_read(int fd, CMS_ContentInfo **content, BIO **output) {
+ BIO *input;
+ *output = NULL;
+
+
+ input = BIO_new_fd(fd, BIO_NOCLOSE);
+ if (input == NULL) {
+ D(ERR, "Unable to open input");
+ goto error;
+ }
+
+ *content = SMIME_read_CMS(input, output);
+ if (*content == NULL) {
+ unsigned long err = ERR_peek_last_error();
+ D(ERR, "Unable to parse input file: %s", ERR_lib_error_string(err));
+ goto error_read;
+ }
+
+ BIO_free(input);
+
+ return 0;
+
+error_read:
+ BIO_free(input);
+error:
+ return 1;
+}
+
+int cert_verify(BIO *content, CMS_ContentInfo *content_info, X509_STORE *store, int *out_fd) {
+ BIO *output_temp;
+ int ret;
+
+ *out_fd = create_temp_file();
+ if (*out_fd < 0) {
+ D(ERR, "unable to create temporary file");
+ return -1;
+ }
+
+ output_temp = BIO_new_fd(*out_fd, BIO_NOCLOSE);
+ if (output_temp == NULL) {
+ D(ERR, "unable to create temporary bio");
+ close(*out_fd);
+ return -1;
+ }
+
+ ret = CMS_verify(content_info, NULL ,store, content, output_temp, 0);
+
+ if (ret == 0) {
+ char buf[256];
+ unsigned long err = ERR_peek_last_error();
+ D(ERR, "Verification failed with reason: %s, %s", ERR_lib_error_string(err), ERR_error_string(err, buf));
+ D(ERR, "Data used: content %d", (int) content);
+ }
+
+ ERR_clear_error();
+ ERR_remove_state(0);
+
+ BIO_free(output_temp);
+
+ return ret;
+}
+
+void cert_release(BIO *content, CMS_ContentInfo *info) {
+ BIO_free(content);
+ CMS_ContentInfo_free(info);
+}
+
diff --git a/fastbootd/secure.h b/fastbootd/secure.h
new file mode 100644
index 000000000..878a64307
--- /dev/null
+++ b/fastbootd/secure.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _FASTBOOTD_SECURE_H
+#define _FASTBOOTD_SECURE_H
+
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+#include <openssl/cms.h>
+
+void cert_init_crypto();
+
+X509_STORE *cert_store_from_path(const char*stream);
+
+static inline void cert_release_store(X509_STORE *store) {
+ X509_STORE_free(store);
+}
+
+int cert_read(int fd, CMS_ContentInfo **content, BIO **output);
+int cert_verify(BIO *content, CMS_ContentInfo *content_info, X509_STORE *store, int *out_fd);
+void cert_release(BIO *content, CMS_ContentInfo *info);
+
+#endif