You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
5.3 KiB
170 lines
5.3 KiB
From 5c2f409c360560c8b99926d6cf1a80419e758b22 Mon Sep 17 00:00:00 2001
|
|
From: Greg Hudson <ghudson@mit.edu>
|
|
Date: Tue, 7 Mar 2023 00:19:33 -0500
|
|
Subject: [PATCH] Add a simple DER support header
|
|
|
|
(cherry picked from commit 548da160b52b25a106e9f6077d6a42c2c049586c)
|
|
---
|
|
src/include/k5-der.h | 149 +++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 149 insertions(+)
|
|
create mode 100644 src/include/k5-der.h
|
|
|
|
diff --git a/src/include/k5-der.h b/src/include/k5-der.h
|
|
new file mode 100644
|
|
index 0000000000..b8371d9b4d
|
|
--- /dev/null
|
|
+++ b/src/include/k5-der.h
|
|
@@ -0,0 +1,149 @@
|
|
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
+/* include/k5-der.h - Distinguished Encoding Rules (DER) declarations */
|
|
+/*
|
|
+ * Copyright (C) 2023 by the Massachusetts Institute of Technology.
|
|
+ * 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.
|
|
+ *
|
|
+ * 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 HOLDER 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.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Most ASN.1 encoding and decoding is done using the table-driven framework in
|
|
+ * libkrb5. When that is not an option, these helpers can be used to encode
|
|
+ * and decode simple types.
|
|
+ */
|
|
+
|
|
+#ifndef K5_DER_H
|
|
+#define K5_DER_H
|
|
+
|
|
+#include <stdint.h>
|
|
+#include <stdbool.h>
|
|
+#include "k5-buf.h"
|
|
+#include "k5-input.h"
|
|
+
|
|
+/* Return the number of bytes needed to encode len as a DER encoding length. */
|
|
+static inline size_t
|
|
+k5_der_len_len(size_t len)
|
|
+{
|
|
+ size_t llen;
|
|
+
|
|
+ if (len < 128)
|
|
+ return 1;
|
|
+ llen = 1;
|
|
+ while (len > 0) {
|
|
+ len >>= 8;
|
|
+ llen++;
|
|
+ }
|
|
+ return llen;
|
|
+}
|
|
+
|
|
+/* Return the number of bytes needed to encode a DER value (with identifier
|
|
+ * byte and length) for a given contents length. */
|
|
+static inline size_t
|
|
+k5_der_value_len(size_t contents_len)
|
|
+{
|
|
+ return 1 + k5_der_len_len(contents_len) + contents_len;
|
|
+}
|
|
+
|
|
+/* Add a DER identifier byte (composed by the caller, including the ASN.1
|
|
+ * class, tag, and constructed bit) and length. */
|
|
+static inline void
|
|
+k5_der_add_taglen(struct k5buf *buf, uint8_t idbyte, size_t len)
|
|
+{
|
|
+ uint8_t *p;
|
|
+ size_t llen = k5_der_len_len(len);
|
|
+
|
|
+ p = k5_buf_get_space(buf, 1 + llen);
|
|
+ if (p == NULL)
|
|
+ return;
|
|
+ *p++ = idbyte;
|
|
+ if (len < 128) {
|
|
+ *p = len;
|
|
+ } else {
|
|
+ *p = 0x80 | (llen - 1);
|
|
+ /* Encode the length bytes backwards so the most significant byte is
|
|
+ * first. */
|
|
+ p += llen;
|
|
+ while (len > 0) {
|
|
+ *--p = len & 0xFF;
|
|
+ len >>= 8;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Add a DER value (identifier byte, length, and contents). */
|
|
+static inline void
|
|
+k5_der_add_value(struct k5buf *buf, uint8_t idbyte, const void *contents,
|
|
+ size_t len)
|
|
+{
|
|
+ k5_der_add_taglen(buf, idbyte, len);
|
|
+ k5_buf_add_len(buf, contents, len);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * If the next byte in in matches idbyte and the subsequent DER length is
|
|
+ * valid, advance in past the value, set *contents_out to the value contents,
|
|
+ * and return true. Otherwise return false. Only set an error on in if the
|
|
+ * next bytes matches idbyte but the ensuing length is invalid. contents_out
|
|
+ * may be aliased to in; it will only be written to on successful decoding of a
|
|
+ * value.
|
|
+ */
|
|
+static inline bool
|
|
+k5_der_get_value(struct k5input *in, uint8_t idbyte,
|
|
+ struct k5input *contents_out)
|
|
+{
|
|
+ uint8_t lenbyte, i;
|
|
+ size_t len;
|
|
+ const void *bytes;
|
|
+
|
|
+ /* Do nothing if in is empty or the next byte doesn't match idbyte. */
|
|
+ if (in->status || in->len == 0 || *in->ptr != idbyte)
|
|
+ return false;
|
|
+
|
|
+ /* Advance past the identifier byte and decode the length. */
|
|
+ (void)k5_input_get_byte(in);
|
|
+ lenbyte = k5_input_get_byte(in);
|
|
+ if (lenbyte < 128) {
|
|
+ len = lenbyte;
|
|
+ } else {
|
|
+ len = 0;
|
|
+ for (i = 0; i < (lenbyte & 0x7F); i++) {
|
|
+ if (len > (SIZE_MAX >> 8)) {
|
|
+ k5_input_set_status(in, EOVERFLOW);
|
|
+ return false;
|
|
+ }
|
|
+ len = (len << 8) | k5_input_get_byte(in);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ bytes = k5_input_get_bytes(in, len);
|
|
+ if (bytes == NULL)
|
|
+ return false;
|
|
+ k5_input_init(contents_out, bytes, len);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+#endif /* K5_DER_H */
|
|
--
|
|
2.45.1
|
|
|