Josh Boyer c115215
From 711fd460b3d44d666fbddd80a91ae5f825c7ebb6 Mon Sep 17 00:00:00 2001
Josh Boyer c2a12cd
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 13:59:15 +0100
Josh Boyer c115215
Subject: [PATCH 01/28] MPILIB: Provide count_leading/trailing_zeros() based
Josh Boyer 5a0e7f0
 on arch functions
Josh Boyer c2a12cd
Josh Boyer 5a0e7f0
Provide count_leading/trailing_zeros() macros based on extant arch bit scanning
Josh Boyer 5a0e7f0
functions rather than reimplementing from scratch in MPILIB.
Josh Boyer 5a0e7f0
Josh Boyer 5a0e7f0
Whilst we're at it, turn count_foo_zeros(n, x) into n = count_foo_zeros(x).
Josh Boyer 5a0e7f0
Josh Boyer 5a0e7f0
Also move the definition to asm-generic as other people may be interested in
Josh Boyer 5a0e7f0
using it.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer 5a0e7f0
Cc: David S. Miller <davem@davemloft.net>
Josh Boyer 5a0e7f0
Cc: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Josh Boyer 5a0e7f0
Cc: Arnd Bergmann <arnd@arndb.com>
Josh Boyer c2a12cd
---
Josh Boyer 306dfcc
 include/asm-generic/bitops/count_zeros.h |  57 +++++++++++++
Josh Boyer 306dfcc
 lib/mpi/longlong.h                       | 138 +------------------------------
Josh Boyer 306dfcc
 lib/mpi/mpi-bit.c                        |   2 +-
Josh Boyer 306dfcc
 lib/mpi/mpi-pow.c                        |   4 +-
Josh Boyer 306dfcc
 4 files changed, 62 insertions(+), 139 deletions(-)
Josh Boyer 5a0e7f0
 create mode 100644 include/asm-generic/bitops/count_zeros.h
Josh Boyer 5a0e7f0
Josh Boyer 5a0e7f0
diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h
Josh Boyer 5a0e7f0
new file mode 100644
Josh Boyer 5a0e7f0
index 0000000..97520d2
Josh Boyer 5a0e7f0
--- /dev/null
Josh Boyer 5a0e7f0
+++ b/include/asm-generic/bitops/count_zeros.h
Josh Boyer 5a0e7f0
@@ -0,0 +1,57 @@
Josh Boyer 5a0e7f0
+/* Count leading and trailing zeros functions
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
Josh Boyer 5a0e7f0
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * This program is free software; you can redistribute it and/or
Josh Boyer 5a0e7f0
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer 5a0e7f0
+ * as published by the Free Software Foundation; either version
Josh Boyer 5a0e7f0
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer 5a0e7f0
+ */
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_
Josh Boyer 5a0e7f0
+#define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#include <asm/bitops.h>
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+/**
Josh Boyer 5a0e7f0
+ * count_leading_zeros - Count the number of zeros from the MSB back
Josh Boyer 5a0e7f0
+ * @x: The value
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * Count the number of leading zeros from the MSB going towards the LSB in @x.
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * If the MSB of @x is set, the result is 0.
Josh Boyer 5a0e7f0
+ * If only the LSB of @x is set, then the result is BITS_PER_LONG-1.
Josh Boyer 5a0e7f0
+ * If @x is 0 then the result is COUNT_LEADING_ZEROS_0.
Josh Boyer 5a0e7f0
+ */
Josh Boyer 5a0e7f0
+static inline int count_leading_zeros(unsigned long x)
Josh Boyer 5a0e7f0
+{
Josh Boyer 5a0e7f0
+	if (sizeof(x) == 4)
Josh Boyer 5a0e7f0
+		return BITS_PER_LONG - fls(x);
Josh Boyer 5a0e7f0
+	else
Josh Boyer 5a0e7f0
+		return BITS_PER_LONG - fls64(x);
Josh Boyer 5a0e7f0
+}
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#define COUNT_LEADING_ZEROS_0 BITS_PER_LONG
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+/**
Josh Boyer 5a0e7f0
+ * count_trailing_zeros - Count the number of zeros from the LSB forwards
Josh Boyer 5a0e7f0
+ * @x: The value
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * Count the number of trailing zeros from the LSB going towards the MSB in @x.
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * If the LSB of @x is set, the result is 0.
Josh Boyer 5a0e7f0
+ * If only the MSB of @x is set, then the result is BITS_PER_LONG-1.
Josh Boyer 5a0e7f0
+ * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0.
Josh Boyer 5a0e7f0
+ */
Josh Boyer 5a0e7f0
+static inline int count_trailing_zeros(unsigned long x)
Josh Boyer 5a0e7f0
+{
Josh Boyer 5a0e7f0
+#define COUNT_TRAILING_ZEROS_0 (-1)
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+	if (sizeof(x) == 4)
Josh Boyer 5a0e7f0
+		return ffs(x);
Josh Boyer 5a0e7f0
+	else
Josh Boyer 5a0e7f0
+		return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0;
Josh Boyer 5a0e7f0
+}
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */
Josh Boyer 5a0e7f0
diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h
Josh Boyer 5a0e7f0
index 29f9862..678ce4f 100644
Josh Boyer 5a0e7f0
--- a/lib/mpi/longlong.h
Josh Boyer 5a0e7f0
+++ b/lib/mpi/longlong.h
Josh Boyer 5a0e7f0
@@ -19,6 +19,8 @@
Josh Boyer 5a0e7f0
  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Josh Boyer 5a0e7f0
  * MA 02111-1307, USA. */
Josh Boyer 5a0e7f0
 
Josh Boyer 5a0e7f0
+#include <asm-generic/bitops/count_zeros.h>
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
 /* You have to define the following before including this file:
Josh Boyer 5a0e7f0
  *
Josh Boyer 5a0e7f0
  * UWtype -- An unsigned type, default type for operations (typically a "word")
Josh Boyer 5a0e7f0
@@ -146,12 +148,6 @@ do { \
Josh Boyer 5a0e7f0
 	: "1" ((USItype)(n1)), \
Josh Boyer 5a0e7f0
 		"r" ((USItype)(n0)), \
Josh Boyer 5a0e7f0
 		"r" ((USItype)(d)))
Josh Boyer 5a0e7f0
-
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-	__asm__ ("clz %0,%1" \
Josh Boyer 5a0e7f0
-	: "=r" ((USItype)(count)) \
Josh Boyer 5a0e7f0
-	: "r" ((USItype)(x)))
Josh Boyer 5a0e7f0
-#define COUNT_LEADING_ZEROS_0 32
Josh Boyer 5a0e7f0
 #endif /* __a29k__ */
Josh Boyer 5a0e7f0
 
Josh Boyer 5a0e7f0
 #if defined(__alpha) && W_TYPE_SIZE == 64
Josh Boyer 5a0e7f0
@@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd();
Josh Boyer 5a0e7f0
 	: "1" ((USItype)(nh)), \
Josh Boyer 5a0e7f0
 		"0" ((USItype)(nl)), \
Josh Boyer 5a0e7f0
 		"g" ((USItype)(d)))
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-	__asm__ ("bsch/1 %1,%0" \
Josh Boyer 5a0e7f0
-	: "=g" (count) \
Josh Boyer 5a0e7f0
-	: "g" ((USItype)(x)), \
Josh Boyer 5a0e7f0
-	     "0" ((USItype)0))
Josh Boyer 5a0e7f0
 #endif
Josh Boyer c2a12cd
 
Josh Boyer 5a0e7f0
 /***************************************
Josh Boyer 5a0e7f0
@@ -354,27 +345,6 @@ do { USItype __r; \
Josh Boyer 5a0e7f0
 } while (0)
Josh Boyer 5a0e7f0
 extern USItype __udiv_qrnnd();
Josh Boyer 5a0e7f0
 #endif /* LONGLONG_STANDALONE */
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-do { \
Josh Boyer 5a0e7f0
-	USItype __tmp; \
Josh Boyer 5a0e7f0
-	__asm__ ( \
Josh Boyer 5a0e7f0
-	"ldi             1,%0\n" \
Josh Boyer 5a0e7f0
-	"extru,=	%1,15,16,%%r0  ; Bits 31..16 zero?\n" \
Josh Boyer 5a0e7f0
-	"extru,tr	%1,15,16,%1    ; No.  Shift down, skip add.\n" \
Josh Boyer 5a0e7f0
-	"ldo		16(%0),%0      ; Yes.	Perform add.\n" \
Josh Boyer 5a0e7f0
-	"extru,=	%1,23,8,%%r0   ; Bits 15..8 zero?\n" \
Josh Boyer 5a0e7f0
-	"extru,tr	%1,23,8,%1     ; No.  Shift down, skip add.\n" \
Josh Boyer 5a0e7f0
-	"ldo		8(%0),%0       ; Yes.	Perform add.\n" \
Josh Boyer 5a0e7f0
-	"extru,=	%1,27,4,%%r0   ; Bits 7..4 zero?\n" \
Josh Boyer 5a0e7f0
-	"extru,tr	%1,27,4,%1     ; No.  Shift down, skip add.\n" \
Josh Boyer 5a0e7f0
-	"ldo		4(%0),%0       ; Yes.	Perform add.\n" \
Josh Boyer 5a0e7f0
-	"extru,=	%1,29,2,%%r0   ; Bits 3..2 zero?\n" \
Josh Boyer 5a0e7f0
-	"extru,tr	%1,29,2,%1     ; No.  Shift down, skip add.\n" \
Josh Boyer 5a0e7f0
-	"ldo		2(%0),%0       ; Yes.	Perform add.\n" \
Josh Boyer 5a0e7f0
-	"extru		%1,30,1,%1     ; Extract bit 1.\n" \
Josh Boyer 5a0e7f0
-	"sub		%0,%1,%0       ; Subtract it.              " \
Josh Boyer 5a0e7f0
-	: "=r" (count), "=r" (__tmp) : "1" (x)); \
Josh Boyer 5a0e7f0
-} while (0)
Josh Boyer 5a0e7f0
 #endif /* hppa */
Josh Boyer 5a0e7f0
 
Josh Boyer 5a0e7f0
 /***************************************
Josh Boyer 5a0e7f0
@@ -457,15 +427,6 @@ do { \
Josh Boyer 5a0e7f0
 	: "0" ((USItype)(n0)), \
Josh Boyer 5a0e7f0
 	     "1" ((USItype)(n1)), \
Josh Boyer 5a0e7f0
 	     "rm" ((USItype)(d)))
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-do { \
Josh Boyer 5a0e7f0
-	USItype __cbtmp; \
Josh Boyer 5a0e7f0
-	__asm__ ("bsrl %1,%0" \
Josh Boyer 5a0e7f0
-	: "=r" (__cbtmp) : "rm" ((USItype)(x))); \
Josh Boyer 5a0e7f0
-	(count) = __cbtmp ^ 31; \
Josh Boyer 5a0e7f0
-} while (0)
Josh Boyer 5a0e7f0
-#define count_trailing_zeros(count, x) \
Josh Boyer 5a0e7f0
-	__asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
Josh Boyer 5a0e7f0
 #ifndef UMUL_TIME
Josh Boyer 5a0e7f0
 #define UMUL_TIME 40
Josh Boyer 5a0e7f0
 #endif
Josh Boyer 5a0e7f0
@@ -536,15 +497,6 @@ do { \
Josh Boyer 5a0e7f0
 	     "dI" ((USItype)(d))); \
Josh Boyer 5a0e7f0
 	(r) = __rq.__i.__l; (q) = __rq.__i.__h; \
Josh Boyer 5a0e7f0
 } while (0)
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-do { \
Josh Boyer 5a0e7f0
-	USItype __cbtmp; \
Josh Boyer 5a0e7f0
-	__asm__ ("scanbit %1,%0" \
Josh Boyer 5a0e7f0
-	: "=r" (__cbtmp) \
Josh Boyer 5a0e7f0
-	: "r" ((USItype)(x))); \
Josh Boyer 5a0e7f0
-	(count) = __cbtmp ^ 31; \
Josh Boyer 5a0e7f0
-} while (0)
Josh Boyer 5a0e7f0
-#define COUNT_LEADING_ZEROS_0 (-32)	/* sic */
Josh Boyer 5a0e7f0
 #if defined(__i960mx)		/* what is the proper symbol to test??? */
Josh Boyer 5a0e7f0
 #define rshift_rhlc(r, h, l, c) \
Josh Boyer 5a0e7f0
 do { \
Josh Boyer 5a0e7f0
@@ -603,11 +555,6 @@ do { \
Josh Boyer 5a0e7f0
 	: "0" ((USItype)(n0)), \
Josh Boyer 5a0e7f0
 	     "1" ((USItype)(n1)), \
Josh Boyer 5a0e7f0
 	     "dmi" ((USItype)(d)))
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-	__asm__ ("bfffo %1{%b2:%b2},%0" \
Josh Boyer 5a0e7f0
-	: "=d" ((USItype)(count)) \
Josh Boyer 5a0e7f0
-	: "od" ((USItype)(x)), "n" (0))
Josh Boyer 5a0e7f0
-#define COUNT_LEADING_ZEROS_0 32
Josh Boyer 5a0e7f0
 #else /* not mc68020 */
Josh Boyer 5a0e7f0
 #define umul_ppmm(xh, xl, a, b) \
Josh Boyer 5a0e7f0
 do { USItype __umul_tmp1, __umul_tmp2; \
Josh Boyer 5a0e7f0
@@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \
Josh Boyer 5a0e7f0
 	     "rJ" ((USItype)(bh)), \
Josh Boyer 5a0e7f0
 	     "rJ" ((USItype)(al)), \
Josh Boyer 5a0e7f0
 	     "rJ" ((USItype)(bl)))
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-do { \
Josh Boyer 5a0e7f0
-	USItype __cbtmp; \
Josh Boyer 5a0e7f0
-	__asm__ ("ff1 %0,%1" \
Josh Boyer 5a0e7f0
-	: "=r" (__cbtmp) \
Josh Boyer 5a0e7f0
-	: "r" ((USItype)(x))); \
Josh Boyer 5a0e7f0
-	(count) = __cbtmp ^ 31; \
Josh Boyer 5a0e7f0
-} while (0)
Josh Boyer 5a0e7f0
-#define COUNT_LEADING_ZEROS_0 63	/* sic */
Josh Boyer 5a0e7f0
 #if defined(__m88110__)
Josh Boyer 5a0e7f0
 #define umul_ppmm(wh, wl, u, v) \
Josh Boyer 5a0e7f0
 do { \
Josh Boyer 5a0e7f0
@@ -779,12 +717,6 @@ do { \
Josh Boyer 5a0e7f0
 	: "0" (__xx.__ll), \
Josh Boyer 5a0e7f0
 	     "g" ((USItype)(d))); \
Josh Boyer 5a0e7f0
 	(r) = __xx.__i.__l; (q) = __xx.__i.__h; })
Josh Boyer 5a0e7f0
-#define count_trailing_zeros(count, x) \
Josh Boyer 5a0e7f0
-do { \
Josh Boyer 5a0e7f0
-	__asm__("ffsd      %2,%0" \
Josh Boyer 5a0e7f0
-	: "=r"((USItype) (count)) \
Josh Boyer 5a0e7f0
-	: "0"((USItype) 0), "r"((USItype) (x))); \
Josh Boyer 5a0e7f0
-	} while (0)
Josh Boyer 5a0e7f0
 #endif /* __ns32000__ */
Josh Boyer 5a0e7f0
 
Josh Boyer 5a0e7f0
 /***************************************
Josh Boyer 5a0e7f0
@@ -855,11 +787,6 @@ do { \
Josh Boyer 5a0e7f0
 		"rI" ((USItype)(al)), \
Josh Boyer 5a0e7f0
 		"r" ((USItype)(bl))); \
Josh Boyer 5a0e7f0
 } while (0)
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-	__asm__ ("{cntlz|cntlzw} %0,%1" \
Josh Boyer 5a0e7f0
-	: "=r" ((USItype)(count)) \
Josh Boyer 5a0e7f0
-	: "r" ((USItype)(x)))
Josh Boyer 5a0e7f0
-#define COUNT_LEADING_ZEROS_0 32
Josh Boyer 5a0e7f0
 #if defined(_ARCH_PPC)
Josh Boyer 5a0e7f0
 #define umul_ppmm(ph, pl, m0, m1) \
Josh Boyer 5a0e7f0
 do { \
Josh Boyer 5a0e7f0
@@ -1001,19 +928,6 @@ do { \
Josh Boyer 5a0e7f0
 } while (0)
Josh Boyer 5a0e7f0
 #define UMUL_TIME 20
Josh Boyer 5a0e7f0
 #define UDIV_TIME 200
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-do { \
Josh Boyer 5a0e7f0
-	if ((x) >= 0x10000) \
Josh Boyer 5a0e7f0
-		__asm__ ("clz     %0,%1" \
Josh Boyer 5a0e7f0
-		: "=r" ((USItype)(count)) \
Josh Boyer 5a0e7f0
-		: "r" ((USItype)(x) >> 16)); \
Josh Boyer 5a0e7f0
-	else { \
Josh Boyer 5a0e7f0
-		__asm__ ("clz   %0,%1" \
Josh Boyer 5a0e7f0
-		: "=r" ((USItype)(count)) \
Josh Boyer 5a0e7f0
-		: "r" ((USItype)(x))); \
Josh Boyer 5a0e7f0
-		(count) += 16; \
Josh Boyer 5a0e7f0
-	} \
Josh Boyer 5a0e7f0
-} while (0)
Josh Boyer 5a0e7f0
 #endif /* RT/ROMP */
Josh Boyer 5a0e7f0
 
Josh Boyer 5a0e7f0
 /***************************************
Josh Boyer 5a0e7f0
@@ -1142,13 +1056,6 @@ do { \
Josh Boyer 5a0e7f0
 	"rI" ((USItype)(d)) \
Josh Boyer 5a0e7f0
 	: "%g1" __AND_CLOBBER_CC)
Josh Boyer 5a0e7f0
 #define UDIV_TIME 37
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-	__asm__ ("scan %1,0,%0" \
Josh Boyer 5a0e7f0
-	: "=r" ((USItype)(x)) \
Josh Boyer 5a0e7f0
-	: "r" ((USItype)(count)))
Josh Boyer 5a0e7f0
-/* Early sparclites return 63 for an argument of 0, but they warn that future
Josh Boyer 5a0e7f0
-	implementations might change this.  Therefore, leave COUNT_LEADING_ZEROS_0
Josh Boyer 5a0e7f0
-	undefined.  */
Josh Boyer 5a0e7f0
 #endif /* __sparclite__ */
Josh Boyer 5a0e7f0
 #endif /* __sparc_v8__ */
Josh Boyer 5a0e7f0
 	/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd.  */
Josh Boyer 5a0e7f0
@@ -1454,47 +1361,6 @@ do { \
Josh Boyer 5a0e7f0
 #define udiv_qrnnd __udiv_qrnnd_c
Josh Boyer 5a0e7f0
 #endif
Josh Boyer 5a0e7f0
 
Josh Boyer 5a0e7f0
-#undef count_leading_zeros
Josh Boyer 5a0e7f0
-#if !defined(count_leading_zeros)
Josh Boyer 5a0e7f0
-	extern
Josh Boyer 5a0e7f0
-#ifdef __STDC__
Josh Boyer 5a0e7f0
-			const
Josh Boyer 5a0e7f0
-#endif
Josh Boyer 5a0e7f0
-			unsigned char __clz_tab[];
Josh Boyer 5a0e7f0
-#define count_leading_zeros(count, x) \
Josh Boyer 5a0e7f0
-do { \
Josh Boyer 5a0e7f0
-	UWtype __xr = (x); \
Josh Boyer 5a0e7f0
-	UWtype __a; \
Josh Boyer 5a0e7f0
-	\
Josh Boyer 5a0e7f0
-	if (W_TYPE_SIZE <= 32) { \
Josh Boyer 5a0e7f0
-		__a = __xr < ((UWtype) 1 << 2*__BITS4) \
Josh Boyer 5a0e7f0
-		? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \
Josh Boyer 5a0e7f0
-		: (__xr < ((UWtype) 1 << 3*__BITS4) ?  2*__BITS4 : 3*__BITS4); \
Josh Boyer 5a0e7f0
-	} \
Josh Boyer 5a0e7f0
-	else { \
Josh Boyer 5a0e7f0
-		for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
Josh Boyer 5a0e7f0
-			if (((__xr >> __a) & 0xff) != 0) \
Josh Boyer 5a0e7f0
-				break; \
Josh Boyer 5a0e7f0
-	} \
Josh Boyer 5a0e7f0
-	\
Josh Boyer 5a0e7f0
-	(count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
Josh Boyer 5a0e7f0
-} while (0)
Josh Boyer 5a0e7f0
-	/* This version gives a well-defined value for zero. */
Josh Boyer 5a0e7f0
-#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
Josh Boyer 5a0e7f0
-#endif
Josh Boyer 5a0e7f0
-
Josh Boyer 5a0e7f0
-#if !defined(count_trailing_zeros)
Josh Boyer 5a0e7f0
-/* Define count_trailing_zeros using count_leading_zeros.  The latter might be
Josh Boyer 5a0e7f0
-	defined in asm, but if it is not, the C version above is good enough.  */
Josh Boyer 5a0e7f0
-#define count_trailing_zeros(count, x) \
Josh Boyer 5a0e7f0
-do { \
Josh Boyer 5a0e7f0
-	UWtype __ctz_x = (x); \
Josh Boyer 5a0e7f0
-	UWtype __ctz_c; \
Josh Boyer 5a0e7f0
-	count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \
Josh Boyer 5a0e7f0
-	(count) = W_TYPE_SIZE - 1 - __ctz_c; \
Josh Boyer 5a0e7f0
-} while (0)
Josh Boyer 5a0e7f0
-#endif
Josh Boyer 5a0e7f0
-
Josh Boyer 5a0e7f0
 #ifndef UDIV_NEEDS_NORMALIZATION
Josh Boyer 5a0e7f0
 #define UDIV_NEEDS_NORMALIZATION 0
Josh Boyer 5a0e7f0
 #endif
Josh Boyer 5a0e7f0
diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c
Josh Boyer 306dfcc
index 5687248..503537e 100644
Josh Boyer 5a0e7f0
--- a/lib/mpi/mpi-bit.c
Josh Boyer 5a0e7f0
+++ b/lib/mpi/mpi-bit.c
Josh Boyer 5a0e7f0
@@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a)
Josh Boyer 5a0e7f0
 	if (a->nlimbs) {
Josh Boyer 5a0e7f0
 		mpi_limb_t alimb = a->d[a->nlimbs - 1];
Josh Boyer 5a0e7f0
 		if (alimb)
Josh Boyer 5a0e7f0
-			count_leading_zeros(n, alimb);
Josh Boyer 5a0e7f0
+			n = count_leading_zeros(alimb);
Josh Boyer 5a0e7f0
 		else
Josh Boyer 5a0e7f0
 			n = BITS_PER_MPI_LIMB;
Josh Boyer 5a0e7f0
 		n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB;
Josh Boyer 5a0e7f0
diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c
Josh Boyer 5a0e7f0
index 67f3e79..5464c87 100644
Josh Boyer 5a0e7f0
--- a/lib/mpi/mpi-pow.c
Josh Boyer 5a0e7f0
+++ b/lib/mpi/mpi-pow.c
Josh Boyer 5a0e7f0
@@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
Josh Boyer 5a0e7f0
 	mp = mp_marker = mpi_alloc_limb_space(msize);
Josh Boyer 5a0e7f0
 	if (!mp)
Josh Boyer 5a0e7f0
 		goto enomem;
Josh Boyer 5a0e7f0
-	count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]);
Josh Boyer 5a0e7f0
+	mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]);
Josh Boyer 5a0e7f0
 	if (mod_shift_cnt)
Josh Boyer 5a0e7f0
 		mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt);
Josh Boyer 5a0e7f0
 	else
Josh Boyer 5a0e7f0
@@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
Josh Boyer 5a0e7f0
 
Josh Boyer 5a0e7f0
 		i = esize - 1;
Josh Boyer 5a0e7f0
 		e = ep[i];
Josh Boyer 5a0e7f0
-		count_leading_zeros(c, e);
Josh Boyer 5a0e7f0
+		c = count_leading_zeros(e);
Josh Boyer 5a0e7f0
 		e = (e << c) << 1;	/* shift the exp bits to the left, lose msb */
Josh Boyer 5a0e7f0
 		c = BITS_PER_MPI_LIMB - 1 - c;
Josh Boyer 5a0e7f0
 
Josh Boyer c2a12cd
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Josh Boyer c115215
From 1d6e2f2b87e6651bead1c0ccca699681f92dd52c Mon Sep 17 00:00:00 2001
Josh Boyer c2a12cd
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 13:59:51 +0100
Josh Boyer c115215
Subject: [PATCH 02/28] KEYS: Create a key type that can be used for general
Josh Boyer 3dd0fcf
 cryptographic operations
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Create a key type that can be used for general cryptographic operations, such
Josh Boyer c2a12cd
as encryption, decryption, signature generation and signature verification.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
The key type is "crypto" and can provide access to a variety of cryptographic
Josh Boyer c2a12cd
algorithms.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c2a12cd
---
Josh Boyer 306dfcc
 Documentation/security/keys-crypto.txt | 181 ++++++++++++++++++++++++++
Josh Boyer 306dfcc
 include/keys/crypto-subtype.h          |  56 ++++++++
Josh Boyer 306dfcc
 include/keys/crypto-type.h             |  25 ++++
Josh Boyer 306dfcc
 security/keys/Kconfig                  |   2 +
Josh Boyer 306dfcc
 security/keys/Makefile                 |   1 +
Josh Boyer 306dfcc
 security/keys/crypto/Kconfig           |   7 +
Josh Boyer 306dfcc
 security/keys/crypto/Makefile          |   7 +
Josh Boyer 306dfcc
 security/keys/crypto/crypto_keys.h     |  28 ++++
Josh Boyer 306dfcc
 security/keys/crypto/crypto_type.c     | 228 +++++++++++++++++++++++++++++++++
Josh Boyer 3dd0fcf
 9 files changed, 535 insertions(+)
Josh Boyer c2a12cd
 create mode 100644 Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
 create mode 100644 include/keys/crypto-subtype.h
Josh Boyer c2a12cd
 create mode 100644 include/keys/crypto-type.h
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/crypto_keys.h
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/crypto_type.c
Josh Boyer c2a12cd
Josh Boyer c2a12cd
diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer c2a12cd
index 0000000..97dee80
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer c2a12cd
+++ b/Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
@@ -0,0 +1,181 @@
Josh Boyer c2a12cd
+			    ======================
Josh Boyer c2a12cd
+			    CRYPTOGRAPHIC KEY TYPE
Josh Boyer c2a12cd
+			    ======================
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+Contents:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+  - Overview.
Josh Boyer c2a12cd
+  - Key identification.
Josh Boyer c2a12cd
+  - Accessing crypto keys.
Josh Boyer c2a12cd
+  - Implementing crypto parsers.
Josh Boyer c2a12cd
+  - Implementing crypto subtypes.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+========
Josh Boyer c2a12cd
+OVERVIEW
Josh Boyer c2a12cd
+========
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The "crypto" key type is designed to be a container for cryptographic keys,
Josh Boyer c2a12cd
+without imposing any particular restrictions on the form of the cryptography or
Josh Boyer c2a12cd
+the key.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The crypto key is given a subtype that defines what sort of data is associated
Josh Boyer c2a12cd
+with the key and provides operations to describe and destroy it.  However, no
Josh Boyer c2a12cd
+requirement is made that the key data actually be loaded into the key.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The crypto key also has a number of data parsers registered with it.  The data
Josh Boyer c2a12cd
+parsers are responsible for extracing information the blobs of data passed to
Josh Boyer c2a12cd
+the instantiator function.  The first data parser that recognises the blob gets
Josh Boyer c2a12cd
+to set the subtype of the key and define the operations that can be done on
Josh Boyer c2a12cd
+that key.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+Completely in-kernel key retention and operation subtypes and parsers can be
Josh Boyer c2a12cd
+defined, but it would also be possible to provide access to cryptographic
Josh Boyer c2a12cd
+hardware (such as a TPM) that might be used to both retain the relevant key and
Josh Boyer c2a12cd
+perform operations using that key.  In such a case, the crypto key would then
Josh Boyer c2a12cd
+merely be an interface to the TPM driver.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+==================
Josh Boyer c2a12cd
+KEY IDENTIFICATION
Josh Boyer c2a12cd
+==================
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+Because the identity of a key is not necessarily known and may not be easily
Josh Boyer c2a12cd
+calculated when a crypto key is allocated, it may not be a simple matter to set
Josh Boyer c2a12cd
+a key description to something that's useful for determining whether this is
Josh Boyer c2a12cd
+the key you're looking for.  Furthermore, it may be necessary to perform a
Josh Boyer c2a12cd
+partial match upon the key identity.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+To help with this, when a key is loaded, the parser calculates the key
Josh Boyer c2a12cd
+fingerprint and stores a copy in the key structure.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The crypto key type's key matching function then performs more checks than just
Josh Boyer c2a12cd
+the straightforward comparison of the description with the criterion string:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+ (1) If the criterion string is of the form "id:<hexdigits>" then the match
Josh Boyer c2a12cd
+     function will examine a key's fingerprint to see if the hex digits given
Josh Boyer c2a12cd
+     after the "id:" match the tail.  For instance:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	keyctl search @s crypto id:5acc2142
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     will match a key with fingerprint:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	1A00 2040 7601 7889 DE11  882C 3823 04AD 5ACC 2142
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+ (2) If the criterion string is of the form "<subtype>:<hexdigits>" then the
Josh Boyer c2a12cd
+     match will match the ID as in (1), but with the added restriction that
Josh Boyer c2a12cd
+     only keys of the specified subtype (e.g. dsa or rsa) will be matched.  For
Josh Boyer c2a12cd
+     instance:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	keyctl search @s crypto dsa:5acc2142
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+Looking in /proc/keys, the last 8 hex digits of the key fingerprint are
Josh Boyer c2a12cd
+displayed, along with the subtype:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	1a39e171 I-----     1 perm 3f010000     0     0 crypto    modsign.0: DSA 5acc2142 []
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+=====================
Josh Boyer c2a12cd
+ACCESSING CRYPTO KEYS
Josh Boyer c2a12cd
+=====================
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+To access crypto keys from within the kernel, the following inclusion is
Josh Boyer c2a12cd
+required:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	#include <keys/crypto-type.h>
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+This gives access to the key type:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	struct key_type key_type_crypto;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+===========================
Josh Boyer c2a12cd
+IMPLEMENTING CRYPTO PARSERS
Josh Boyer c2a12cd
+===========================
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The crypto key type keeps a list of registered data parsers.  An example of
Josh Boyer c2a12cd
+such a parser is one that parses OpenPGP packet formatted data [RFC 4880].
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+During key instantiation each parser in the list is tried until one doesn't
Josh Boyer c2a12cd
+return -EBADMSG.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The parser definition structure looks like the following:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	struct crypto_key_parser {
Josh Boyer c2a12cd
+		struct module		*owner;
Josh Boyer c2a12cd
+		const char		*name;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		int (*instantiate)(struct key *key,
Josh Boyer c2a12cd
+				   const void *data, size_t datalen);
Josh Boyer c2a12cd
+	};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The owner and name fields should be set to the owning module and the name of
Josh Boyer c2a12cd
+the parser.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+There are a number of operations defined by the parser.  They are all optional,
Josh Boyer c2a12cd
+but it is expected that at least one will be defined.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+ (1) instantiate().
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     The arguments are the same as for the instantiate function in the key
Josh Boyer c2a12cd
+     type.  'key' is the crypto key being instantiated; data and datalen are
Josh Boyer c2a12cd
+     the instantiation data, presumably containing cryptographic key data, and
Josh Boyer c2a12cd
+     the length of that data.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     If the data format is not recognised, -EBADMSG should be returned.  If it
Josh Boyer c2a12cd
+     is recognised, but the key cannot for some reason be set up, some other
Josh Boyer c2a12cd
+     negative error code should be returned.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     If the key can be successfully set up, then key->payload should be set to
Josh Boyer c2a12cd
+     point to the retained data, key->type_data.p[0] should be set to point to
Josh Boyer c2a12cd
+     the subtype chosen and key->type_data.p[1] should be set to point to a
Josh Boyer c2a12cd
+     copy of the key's identity string and 0 should be returned.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     The key's identity string may be partially matched upon.  For a public-key
Josh Boyer c2a12cd
+     algorithm such as RSA and DSA this will likely be a printable hex version
Josh Boyer c2a12cd
+     of the key's fingerprint.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+Functions are provided to register and unregister parsers:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	int register_crypto_key_parser(struct crypto_key_parser *parser);
Josh Boyer c2a12cd
+	void unregister_crypto_key_parser(struct crypto_key_parser *subtype);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+Parsers may not have the same name.  The names are only used for displaying in
Josh Boyer c2a12cd
+debugging messages.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+============================
Josh Boyer c2a12cd
+IMPLEMENTING CRYPTO SUBTYPES
Josh Boyer c2a12cd
+============================
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The parser selects the appropriate subtype directly and sets it on the key; the
Josh Boyer c2a12cd
+crypto key then retains a reference on the subtype module (which means the
Josh Boyer c2a12cd
+parser can be removed thereafter).
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The subtype definition structure looks like the following:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	struct crypto_key_subtype {
Josh Boyer c2a12cd
+		struct module		*owner;
Josh Boyer c2a12cd
+		const char		*name;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		void (*describe)(const struct key *key, struct seq_file *m);
Josh Boyer c2a12cd
+		void (*destroy)(void *payload);
Josh Boyer c2a12cd
+	};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The owner and name fields should be set to the owning module and the name of
Josh Boyer c2a12cd
+the subtype.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+There are a number of operations defined by the subtype:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+ (1) describe().
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     Mandatory.  This allows the subtype to display something in /proc/keys
Josh Boyer c2a12cd
+     against the key.  For instance the name of the public key algorithm type
Josh Boyer c2a12cd
+     could be displayed.  The key type will display the tail of the key
Josh Boyer c2a12cd
+     identity string after this.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+ (2) destroy().
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     Mandatory.  This should free the memory associated with the key.  The
Josh Boyer c2a12cd
+     crypto key will look after freeing the fingerprint and releasing the
Josh Boyer c2a12cd
+     reference on the subtype module.
Josh Boyer c2a12cd
diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer c2a12cd
index 0000000..fa87555
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer c2a12cd
+++ b/include/keys/crypto-subtype.h
Josh Boyer c2a12cd
@@ -0,0 +1,56 @@
Josh Boyer c2a12cd
+/* Cryptographic key subtype
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * See Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#ifndef _KEYS_CRYPTO_SUBTYPE_H
Josh Boyer c2a12cd
+#define _KEYS_CRYPTO_SUBTYPE_H
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#include <linux/seq_file.h>
Josh Boyer c2a12cd
+#include <keys/crypto-type.h>
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern struct key_type key_type_crypto;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Keys of this type declare a subtype that indicates the handlers and
Josh Boyer c2a12cd
+ * capabilities.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+struct crypto_key_subtype {
Josh Boyer c2a12cd
+	struct module		*owner;
Josh Boyer c2a12cd
+	const char		*name;
Josh Boyer c2a12cd
+	unsigned short		name_len;	/* length of name */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	void (*describe)(const struct key *key, struct seq_file *m);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	void (*destroy)(void *payload);
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Data parser.  Called during instantiation and signature verification
Josh Boyer c2a12cd
+ * initiation.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+struct crypto_key_parser {
Josh Boyer c2a12cd
+	struct list_head	link;
Josh Boyer c2a12cd
+	struct module		*owner;
Josh Boyer c2a12cd
+	const char		*name;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* Attempt to instantiate a key from the data blob passed to add_key()
Josh Boyer c2a12cd
+	 * or keyctl_instantiate().
Josh Boyer c2a12cd
+	 *
Josh Boyer c2a12cd
+	 * Return EBADMSG if not recognised.
Josh Boyer c2a12cd
+	 */
Josh Boyer c2a12cd
+	int (*instantiate)(struct key *key, const void *data, size_t datalen);
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern int register_crypto_key_parser(struct crypto_key_parser *);
Josh Boyer c2a12cd
+extern void unregister_crypto_key_parser(struct crypto_key_parser *);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#endif /* _KEYS_CRYPTO_SUBTYPE_H */
Josh Boyer c2a12cd
diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer c2a12cd
index 0000000..47c00c7
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer c2a12cd
+++ b/include/keys/crypto-type.h
Josh Boyer c2a12cd
@@ -0,0 +1,25 @@
Josh Boyer c2a12cd
+/* Cryptographic key type interface
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * See Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#ifndef _KEYS_CRYPTO_TYPE_H
Josh Boyer c2a12cd
+#define _KEYS_CRYPTO_TYPE_H
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#include <linux/key-type.h>
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern struct key_type key_type_crypto;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * The payload is at the discretion of the subtype.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#endif /* _KEYS_CRYPTO_TYPE_H */
Josh Boyer c2a12cd
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
Josh Boyer 3dd0fcf
index a90d6d3..992fe52 100644
Josh Boyer c2a12cd
--- a/security/keys/Kconfig
Josh Boyer c2a12cd
+++ b/security/keys/Kconfig
Josh Boyer 3dd0fcf
@@ -69,3 +69,5 @@ config KEYS_DEBUG_PROC_KEYS
Josh Boyer c2a12cd
 	  the resulting table.
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
 	  If you are unsure as to whether this is required, answer N.
Josh Boyer c2a12cd
+
Josh Boyer 3dd0fcf
+source security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
diff --git a/security/keys/Makefile b/security/keys/Makefile
Josh Boyer 3dd0fcf
index 504aaa0..67dae73 100644
Josh Boyer 3dd0fcf
--- a/security/keys/Makefile
Josh Boyer 3dd0fcf
+++ b/security/keys/Makefile
Josh Boyer 3dd0fcf
@@ -24,3 +24,4 @@ obj-$(CONFIG_SYSCTL) += sysctl.o
Josh Boyer 3dd0fcf
 #
Josh Boyer 3dd0fcf
 obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
Josh Boyer 3dd0fcf
 obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
Josh Boyer 3dd0fcf
+obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto/
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
new file mode 100644
Josh Boyer 3dd0fcf
index 0000000..3d15710
Josh Boyer 3dd0fcf
--- /dev/null
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
@@ -0,0 +1,7 @@
Josh Boyer c2a12cd
+config CRYPTO_KEY_TYPE
Josh Boyer c2a12cd
+	tristate "Cryptographic key type"
Josh Boyer c2a12cd
+	depends on KEYS
Josh Boyer c2a12cd
+	help
Josh Boyer c2a12cd
+	  This option provides support for a type of key that holds the keys
Josh Boyer c2a12cd
+	  required for cryptographic operations such as encryption, decryption,
Josh Boyer c2a12cd
+	  signature generation and signature verification.
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
new file mode 100644
Josh Boyer 3dd0fcf
index 0000000..36db1d5
Josh Boyer 3dd0fcf
--- /dev/null
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
@@ -0,0 +1,7 @@
Josh Boyer 3dd0fcf
+#
Josh Boyer 3dd0fcf
+# Makefile for cryptographic keys
Josh Boyer 3dd0fcf
+#
Josh Boyer 3dd0fcf
+
Josh Boyer c2a12cd
+obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+crypto_keys-y := crypto_type.o
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/crypto_keys.h b/security/keys/crypto/crypto_keys.h
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer c2a12cd
index 0000000..a339ce0
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/crypto_keys.h
Josh Boyer c2a12cd
@@ -0,0 +1,28 @@
Josh Boyer c2a12cd
+/* Internal crypto type stuff
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static inline
Josh Boyer c2a12cd
+struct crypto_key_subtype *crypto_key_subtype(const struct key *key)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	return key->type_data.p[0];
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static inline char *crypto_key_id(const struct key *key)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	return key->type_data.p[1];
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * crypto_type.c
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+extern struct list_head crypto_key_parsers;
Josh Boyer c2a12cd
+extern struct rw_semaphore crypto_key_parsers_sem;
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/crypto_type.c b/security/keys/crypto/crypto_type.c
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer c2a12cd
index 0000000..33d279b
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/crypto_type.c
Josh Boyer c2a12cd
@@ -0,0 +1,228 @@
Josh Boyer c2a12cd
+/* Cryptographic key type
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * See Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+#include <keys/crypto-subtype.h>
Josh Boyer c2a12cd
+#include <linux/seq_file.h>
Josh Boyer c2a12cd
+#include <linux/module.h>
Josh Boyer c2a12cd
+#include <linux/slab.h>
Josh Boyer c2a12cd
+#include "crypto_keys.h"
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+MODULE_LICENSE("GPL");
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+LIST_HEAD(crypto_key_parsers);
Josh Boyer c2a12cd
+DECLARE_RWSEM(crypto_key_parsers_sem);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Match crypto_keys on (part of) their name
Josh Boyer c2a12cd
+ * We have some shorthand methods for matching keys.  We allow:
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ *	"<desc>"	- request a key by description
Josh Boyer c2a12cd
+ *	"id:<id>"	- request a key matching the ID
Josh Boyer c2a12cd
+ *	"<subtype>:<id>" - request a key of a subtype
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int crypto_key_match(const struct key *key, const void *description)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	const struct crypto_key_subtype *subtype = crypto_key_subtype(key);
Josh Boyer c2a12cd
+	const char *spec = description;
Josh Boyer c2a12cd
+	const char *id, *kid;
Josh Boyer c2a12cd
+	ptrdiff_t speclen;
Josh Boyer c2a12cd
+	size_t idlen, kidlen;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (!subtype || !spec || !*spec)
Josh Boyer c2a12cd
+		return 0;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* See if the full key description matches as is */
Josh Boyer c2a12cd
+	if (key->description && strcmp(key->description, description) == 0)
Josh Boyer c2a12cd
+		return 1;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* All tests from here on break the criterion description into a
Josh Boyer c2a12cd
+	 * specifier, a colon and then an identifier.
Josh Boyer c2a12cd
+	 */
Josh Boyer c2a12cd
+	id = strchr(spec, ':');
Josh Boyer c2a12cd
+	if (!id)
Josh Boyer c2a12cd
+		return 0;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	speclen = id - spec;
Josh Boyer c2a12cd
+	id++;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* Anything after here requires a partial match on the ID string */
Josh Boyer c2a12cd
+	kid = crypto_key_id(key);
Josh Boyer c2a12cd
+	if (!kid)
Josh Boyer c2a12cd
+		return 0;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	idlen = strlen(id);
Josh Boyer c2a12cd
+	kidlen = strlen(kid);
Josh Boyer c2a12cd
+	if (idlen > kidlen)
Josh Boyer c2a12cd
+		return 0;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	kid += kidlen - idlen;
Josh Boyer c2a12cd
+	if (strcasecmp(id, kid) != 0)
Josh Boyer c2a12cd
+		return 0;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (speclen == 2 &&
Josh Boyer c2a12cd
+	    memcmp(spec, "id", 2) == 0)
Josh Boyer c2a12cd
+		return 1;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (speclen == subtype->name_len &&
Josh Boyer c2a12cd
+	    memcmp(spec, subtype->name, speclen) == 0)
Josh Boyer c2a12cd
+		return 1;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	return 0;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Describe the crypto key
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static void crypto_key_describe(const struct key *key, struct seq_file *m)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	const struct crypto_key_subtype *subtype = crypto_key_subtype(key);
Josh Boyer c2a12cd
+	const char *kid = crypto_key_id(key);
Josh Boyer c2a12cd
+	size_t n;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	seq_puts(m, key->description);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (subtype) {
Josh Boyer c2a12cd
+		seq_puts(m, ": ");
Josh Boyer c2a12cd
+		subtype->describe(key, m);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		if (kid) {
Josh Boyer c2a12cd
+			seq_putc(m, ' ');
Josh Boyer c2a12cd
+			n = strlen(kid);
Josh Boyer c2a12cd
+			if (n <= 8)
Josh Boyer c2a12cd
+				seq_puts(m, kid);
Josh Boyer c2a12cd
+			else
Josh Boyer c2a12cd
+				seq_puts(m, kid + n - 8);
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		seq_puts(m, " [");
Josh Boyer c2a12cd
+		/* put something here to indicate the key's capabilities */
Josh Boyer c2a12cd
+		seq_putc(m, ']');
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Instantiate a crypto_key defined key
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int crypto_key_instantiate(struct key *key,
Josh Boyer c2a12cd
+				  const void *data, size_t datalen)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct crypto_key_parser *parser;
Josh Boyer c2a12cd
+	int ret;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("==>%s()\n", __func__);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (datalen == 0)
Josh Boyer c2a12cd
+		return -EINVAL;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	down_read(&crypto_key_parsers_sem);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	ret = -EBADMSG;
Josh Boyer c2a12cd
+	list_for_each_entry(parser, &crypto_key_parsers, link) {
Josh Boyer c2a12cd
+		pr_debug("Trying parser '%s'\n", parser->name);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		ret = parser->instantiate(key, data, datalen);
Josh Boyer c2a12cd
+		if (ret != -EBADMSG) {
Josh Boyer c2a12cd
+			pr_debug("Parser recognised the format (ret %d)\n",
Josh Boyer c2a12cd
+				 ret);
Josh Boyer c2a12cd
+			break;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	up_read(&crypto_key_parsers_sem);
Josh Boyer c2a12cd
+	pr_devel("<==%s() = %d\n", __func__, ret);
Josh Boyer c2a12cd
+	return ret;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * dispose of the data dangling from the corpse of a crypto key
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static void crypto_key_destroy(struct key *key)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct crypto_key_subtype *subtype = crypto_key_subtype(key);
Josh Boyer c2a12cd
+	if (subtype) {
Josh Boyer c2a12cd
+		subtype->destroy(key->payload.data);
Josh Boyer c2a12cd
+		module_put(subtype->owner);
Josh Boyer c2a12cd
+		key->type_data.p[0] = NULL;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+	kfree(key->type_data.p[1]);
Josh Boyer c2a12cd
+	key->type_data.p[1] = NULL;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct key_type key_type_crypto = {
Josh Boyer c2a12cd
+	.name		= "crypto",
Josh Boyer c2a12cd
+	.instantiate	= crypto_key_instantiate,
Josh Boyer c2a12cd
+	.match		= crypto_key_match,
Josh Boyer c2a12cd
+	.destroy	= crypto_key_destroy,
Josh Boyer c2a12cd
+	.describe	= crypto_key_describe,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(key_type_crypto);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * register_crypto_key_parser - Register a crypto key blob parser
Josh Boyer c2a12cd
+ * @parser: The parser to register
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+int register_crypto_key_parser(struct crypto_key_parser *parser)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct crypto_key_parser *cursor;
Josh Boyer c2a12cd
+	int ret;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	down_write(&crypto_key_parsers_sem);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	list_for_each_entry(cursor, &crypto_key_parsers, link) {
Josh Boyer c2a12cd
+		if (strcmp(cursor->name, parser->name) == 0) {
Josh Boyer c2a12cd
+			pr_err("Crypto key parser '%s' already registered\n",
Josh Boyer c2a12cd
+			       parser->name);
Josh Boyer c2a12cd
+			ret = -EEXIST;
Josh Boyer c2a12cd
+			goto out;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	list_add_tail(&parser->link, &crypto_key_parsers);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_notice("Crypto key parser '%s' registered\n", parser->name);
Josh Boyer c2a12cd
+	ret = 0;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+out:
Josh Boyer c2a12cd
+	up_write(&crypto_key_parsers_sem);
Josh Boyer c2a12cd
+	return ret;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(register_crypto_key_parser);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * unregister_crypto_key_parser - Unregister a crypto key blob parser
Josh Boyer c2a12cd
+ * @parser: The parser to unregister
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+void unregister_crypto_key_parser(struct crypto_key_parser *parser)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	down_write(&crypto_key_parsers_sem);
Josh Boyer c2a12cd
+	list_del(&parser->link);
Josh Boyer c2a12cd
+	up_write(&crypto_key_parsers_sem);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_notice("Crypto key parser '%s' unregistered\n", parser->name);
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(unregister_crypto_key_parser);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Module stuff
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int __init crypto_key_init(void)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	return register_key_type(&key_type_crypto);
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static void __exit crypto_key_cleanup(void)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	unregister_key_type(&key_type_crypto);
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+module_init(crypto_key_init);
Josh Boyer c2a12cd
+module_exit(crypto_key_cleanup);
Josh Boyer c2a12cd
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Josh Boyer c115215
From 24d9655ce0fc046012078867baaedd3bf2eaedd2 Mon Sep 17 00:00:00 2001
Josh Boyer c2a12cd
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 13:59:51 +0100
Josh Boyer c115215
Subject: [PATCH 03/28] KEYS: Add signature verification facility
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Add a facility whereby a key subtype may be asked to verify a signature against
Josh Boyer c2a12cd
the data it is purported to have signed.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
This adds four routines:
Josh Boyer c2a12cd
Josh Boyer c2a12cd
 (1) struct crypto_key_verify_context *
Josh Boyer c2a12cd
     verify_sig_begin(struct key *keyring, const void *sig, size_t siglen);
Josh Boyer c2a12cd
Josh Boyer c2a12cd
     This sets up a verification context for the given signature using
Josh Boyer c2a12cd
     information in that signature to select a key from the specified keyring
Josh Boyer c2a12cd
     and to request a hash algorithm from the crypto layer.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
 (2) int verify_sig_add_data(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
			     const void *data, size_t datalen);
Josh Boyer c2a12cd
Josh Boyer c2a12cd
     Incrementally supply data to be signed.  May be called multiple times.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
 (3) int verify_sig_end(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
			const void *sig, size_t siglen);
Josh Boyer c2a12cd
Josh Boyer c2a12cd
     Complete the verification process and return the result.  -EKEYREJECTED
Josh Boyer c2a12cd
     will indicate that the verification failed and 0 will indicate success.
Josh Boyer c2a12cd
     Other errors are also possible.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
 (4) void verify_sig_cancel(struct crypto_key_verify_context *ctx);
Josh Boyer c2a12cd
Josh Boyer c2a12cd
     Cancel the verification process.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c2a12cd
---
Josh Boyer 306dfcc
 Documentation/security/keys-crypto.txt | 101 +++++++++++++++++++++++++++++
Josh Boyer 306dfcc
 include/keys/crypto-subtype.h          |  21 +++++++
Josh Boyer 306dfcc
 include/keys/crypto-type.h             |   9 +++
Josh Boyer 306dfcc
 security/keys/crypto/Makefile          |   2 +-
Josh Boyer 306dfcc
 security/keys/crypto/crypto_verify.c   | 112 +++++++++++++++++++++++++++++++++
Josh Boyer 5a0e7f0
 5 files changed, 244 insertions(+), 1 deletion(-)
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/crypto_verify.c
Josh Boyer c2a12cd
Josh Boyer c2a12cd
diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
index 97dee80..a964717 100644
Josh Boyer c2a12cd
--- a/Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
+++ b/Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
@@ -7,6 +7,7 @@ Contents:
Josh Boyer c2a12cd
   - Overview.
Josh Boyer c2a12cd
   - Key identification.
Josh Boyer c2a12cd
   - Accessing crypto keys.
Josh Boyer c2a12cd
+    - Signature verification.
Josh Boyer c2a12cd
   - Implementing crypto parsers.
Josh Boyer c2a12cd
   - Implementing crypto subtypes.
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
@@ -89,6 +90,65 @@ This gives access to the key type:
Josh Boyer c2a12cd
 	struct key_type key_type_crypto;
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
+SIGNATURE VERIFICATION
Josh Boyer c2a12cd
+----------------------
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+The four operations that can perform cryptographic signature verification,
Josh Boyer c2a12cd
+using one of a set of keys to provide the public key:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+ (1) Begin verification procedure.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	struct crypto_key_verify_context *
Josh Boyer c2a12cd
+	verify_sig_begin(struct key *keyring, const void *sig, size_t siglen);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     This function sets up a verification context from the information in the
Josh Boyer c2a12cd
+     signature and looks for a suitable key in the keyring.  The signature blob
Josh Boyer c2a12cd
+     must be presented again at the end of the procedure.  The keys will be
Josh Boyer c2a12cd
+     checked against parameters in the signature, and if the matching one is
Josh Boyer c2a12cd
+     not found then -ENOKEY will be returned.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     The hashing algorithm, if such a thing applies, will be determined from
Josh Boyer c2a12cd
+     information in the signature and the appropriate crypto module will be
Josh Boyer c2a12cd
+     used.  -ENOPKG will be returned if the hash algorithm is unavailable.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     The return value is an opaque pointer to be passed to the other functions,
Josh Boyer c2a12cd
+     or a negative error code.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+ (2) Indicate data to be verified.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	int verify_sig_add_data(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+				const void *data, size_t datalen);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     This function is used to shovel data to the verification procedure so that
Josh Boyer c2a12cd
+     it can load it into the hash, pass it to hardware or whatever is
Josh Boyer c2a12cd
+     appropriate for the algorithm being employed.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     The data is not canonicalised for the document type specified in the
Josh Boyer c2a12cd
+     signature.  The caller must do that.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     It will return 0 if successful and a negative error code if not.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+ (3) Complete the verification process.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	int verify_sig_end(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+			   const void *sig, size_t siglen);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     This function performs the actual signature verification step and cleans
Josh Boyer c2a12cd
+     up the resources allocated at the beginning.  The signature must be
Josh Boyer c2a12cd
+     presented again as some of the data therein may need to be added to the
Josh Boyer c2a12cd
+     internal hash.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     It will return -EKEYREJECTED if the signature didn't match, 0 if
Josh Boyer c2a12cd
+     successful and may return other errors as appropriate.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+ (4) Cancel the verification process.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	void verify_sig_cancel(struct crypto_key_verify_context *ctx);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     This function cleans up the resources allocated at the beginning.  This is
Josh Boyer c2a12cd
+     not necessary if verify_sig_end() was called.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
 ===========================
Josh Boyer c2a12cd
 IMPLEMENTING CRYPTO PARSERS
Josh Boyer c2a12cd
 ===========================
Josh Boyer c2a12cd
@@ -96,6 +156,7 @@ IMPLEMENTING CRYPTO PARSERS
Josh Boyer c2a12cd
 The crypto key type keeps a list of registered data parsers.  An example of
Josh Boyer c2a12cd
 such a parser is one that parses OpenPGP packet formatted data [RFC 4880].
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
 During key instantiation each parser in the list is tried until one doesn't
Josh Boyer c2a12cd
 return -EBADMSG.
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
@@ -107,6 +168,8 @@ The parser definition structure looks like the following:
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
 		int (*instantiate)(struct key *key,
Josh Boyer c2a12cd
 				   const void *data, size_t datalen);
Josh Boyer c2a12cd
+		struct crypto_key_verify_context *(*verify_sig_begin)(
Josh Boyer c2a12cd
+			struct key *keyring, const u8 *sig, size_t siglen);
Josh Boyer c2a12cd
 	};
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
 The owner and name fields should be set to the owning module and the name of
Josh Boyer c2a12cd
@@ -135,6 +198,44 @@ but it is expected that at least one will be defined.
Josh Boyer c2a12cd
      algorithm such as RSA and DSA this will likely be a printable hex version
Josh Boyer c2a12cd
      of the key's fingerprint.
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
+ (2) verify_sig_begin().
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     This is similar in concept to the instantiate() function, except that it
Josh Boyer c2a12cd
+     is given a signature blob to parse rather than a key data blob.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     If the data format is not recognised, -EBADMSG should be returned.  If it
Josh Boyer c2a12cd
+     is recognised, but the signature verification process cannot for some
Josh Boyer c2a12cd
+     reason be set up, some other negative error code should be returned.
Josh Boyer c2a12cd
+     -ENOKEY should be used to indicate that no matching key is available and
Josh Boyer c2a12cd
+     -ENOPKG should be returned if the hash algorithm or the verification
Josh Boyer c2a12cd
+     algorithm are unavailable.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     If successful, the parser should allocate a verification context and embed
Josh Boyer c2a12cd
+     the following struct in it:
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	struct crypto_key_verify_context {
Josh Boyer c2a12cd
+		struct key *key;
Josh Boyer c2a12cd
+		int (*add_data)(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+				const void *data, size_t datalen);
Josh Boyer c2a12cd
+		int (*end)(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+			   const u8 *sig, size_t siglen);
Josh Boyer c2a12cd
+		void (*cancel)(struct crypto_key_verify_context *ctx);
Josh Boyer c2a12cd
+	};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     and return a pointer to this to the caller, who will then pass it to the
Josh Boyer c2a12cd
+     verification operation wrappers described in the "Signature Verification"
Josh Boyer c2a12cd
+     section.  The three operation pointers here correspond exactly to those
Josh Boyer c2a12cd
+     wrappers and are all mandatory.  container_of() should be used to retrieve
Josh Boyer c2a12cd
+     the actual context.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     Note that the crypto key type retains a reference on the parser module for
Josh Boyer c2a12cd
+     the lifetime of this context, though the operation pointers need not point
Josh Boyer c2a12cd
+     into this module.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+     The parser should also record a pointer to the key selected and take a
Josh Boyer c2a12cd
+     reference on that key with key_get().
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
 Functions are provided to register and unregister parsers:
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
 	int register_crypto_key_parser(struct crypto_key_parser *parser);
Josh Boyer c2a12cd
diff --git a/include/keys/crypto-subtype.h b/include/keys/crypto-subtype.h
Josh Boyer c2a12cd
index fa87555..f2b927a 100644
Josh Boyer c2a12cd
--- a/include/keys/crypto-subtype.h
Josh Boyer c2a12cd
+++ b/include/keys/crypto-subtype.h
Josh Boyer c2a12cd
@@ -20,6 +20,20 @@
Josh Boyer c2a12cd
 extern struct key_type key_type_crypto;
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
 /*
Josh Boyer c2a12cd
+ * Context base for signature verification methods.  Allocated by the subtype
Josh Boyer c2a12cd
+ * and presumably embedded in something appropriate.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+struct crypto_key_verify_context {
Josh Boyer c2a12cd
+	struct key *key;
Josh Boyer c2a12cd
+	struct crypto_key_parser *parser;
Josh Boyer c2a12cd
+	int (*add_data)(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+			const void *data, size_t datalen);
Josh Boyer c2a12cd
+	int (*end)(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+		   const u8 *sig, size_t siglen);
Josh Boyer c2a12cd
+	void (*cancel)(struct crypto_key_verify_context *ctx);
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
  * Keys of this type declare a subtype that indicates the handlers and
Josh Boyer c2a12cd
  * capabilities.
Josh Boyer c2a12cd
  */
Josh Boyer c2a12cd
@@ -48,6 +62,13 @@ struct crypto_key_parser {
Josh Boyer c2a12cd
 	 * Return EBADMSG if not recognised.
Josh Boyer c2a12cd
 	 */
Josh Boyer c2a12cd
 	int (*instantiate)(struct key *key, const void *data, size_t datalen);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* Attempt to recognise a signature blob and find a matching key.
Josh Boyer c2a12cd
+	 *
Josh Boyer c2a12cd
+	 * Return EBADMSG if not recognised.
Josh Boyer c2a12cd
+	 */
Josh Boyer c2a12cd
+	struct crypto_key_verify_context *(*verify_sig_begin)(
Josh Boyer c2a12cd
+		struct key *keyring, const u8 *sig, size_t siglen);
Josh Boyer c2a12cd
 };
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
 extern int register_crypto_key_parser(struct crypto_key_parser *);
Josh Boyer c2a12cd
diff --git a/include/keys/crypto-type.h b/include/keys/crypto-type.h
Josh Boyer c2a12cd
index 47c00c7..6b93366 100644
Josh Boyer c2a12cd
--- a/include/keys/crypto-type.h
Josh Boyer c2a12cd
+++ b/include/keys/crypto-type.h
Josh Boyer c2a12cd
@@ -18,6 +18,15 @@
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
 extern struct key_type key_type_crypto;
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
+struct crypto_key_verify_context;
Josh Boyer c2a12cd
+extern struct crypto_key_verify_context *verify_sig_begin(
Josh Boyer c2a12cd
+	struct key *key, const void *sig, size_t siglen);
Josh Boyer c2a12cd
+extern int verify_sig_add_data(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+			       const void *data, size_t datalen);
Josh Boyer c2a12cd
+extern int verify_sig_end(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+			  const void *sig, size_t siglen);
Josh Boyer c2a12cd
+extern void verify_sig_cancel(struct crypto_key_verify_context *ctx);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
 /*
Josh Boyer c2a12cd
  * The payload is at the discretion of the subtype.
Josh Boyer c2a12cd
  */
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
index 36db1d5..67001bc 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
@@ -4,4 +4,4 @@
Josh Boyer 3dd0fcf
 
Josh Boyer c2a12cd
 obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
-crypto_keys-y := crypto_type.o
Josh Boyer c2a12cd
+crypto_keys-y := crypto_type.o crypto_verify.o
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/crypto_verify.c b/security/keys/crypto/crypto_verify.c
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer 5a0e7f0
index 0000000..3f2964b
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/crypto_verify.c
Josh Boyer 5a0e7f0
@@ -0,0 +1,112 @@
Josh Boyer c2a12cd
+/* Signature verification with a crypto key
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * See Documentation/security/keys-crypto.txt
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#include <keys/crypto-subtype.h>
Josh Boyer c2a12cd
+#include <linux/module.h>
Josh Boyer 5a0e7f0
+#include <linux/err.h>
Josh Boyer c2a12cd
+#include "crypto_keys.h"
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * verify_sig_begin - Initiate the use of a crypto key to verify a signature
Josh Boyer c2a12cd
+ * @keyring: The public keys to verify against
Josh Boyer c2a12cd
+ * @sig: The signature data
Josh Boyer c2a12cd
+ * @siglen: The signature length
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Returns a context or an error.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+struct crypto_key_verify_context *verify_sig_begin(
Josh Boyer c2a12cd
+	struct key *keyring, const void *sig, size_t siglen)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct crypto_key_verify_context *ret;
Josh Boyer c2a12cd
+	struct crypto_key_parser *parser;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("==>%s()\n", __func__);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (siglen == 0 || !sig)
Josh Boyer c2a12cd
+		return ERR_PTR(-EINVAL);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	down_read(&crypto_key_parsers_sem);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	ret = ERR_PTR(-EBADMSG);
Josh Boyer c2a12cd
+	list_for_each_entry(parser, &crypto_key_parsers, link) {
Josh Boyer c2a12cd
+		if (parser->verify_sig_begin) {
Josh Boyer c2a12cd
+			if (!try_module_get(parser->owner))
Josh Boyer c2a12cd
+				continue;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+			pr_debug("Trying parser '%s'\n", parser->name);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+			ret = parser->verify_sig_begin(keyring, sig, siglen);
Josh Boyer c2a12cd
+			if (IS_ERR(ret))
Josh Boyer c2a12cd
+				module_put(parser->owner);
Josh Boyer c2a12cd
+			else
Josh Boyer c2a12cd
+				ret->parser = parser;
Josh Boyer c2a12cd
+			if (ret != ERR_PTR(-EBADMSG)) {
Josh Boyer c2a12cd
+				pr_debug("Parser recognised the format"
Josh Boyer c2a12cd
+					 " (ret %ld)\n",
Josh Boyer c2a12cd
+					 PTR_ERR(ret));
Josh Boyer c2a12cd
+				break;
Josh Boyer c2a12cd
+			}
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	up_read(&crypto_key_parsers_sem);
Josh Boyer c2a12cd
+	pr_devel("<==%s() = %p\n", __func__, ret);
Josh Boyer c2a12cd
+	return ret;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(verify_sig_begin);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * verify_sig_add_data - Incrementally provide data to be verified
Josh Boyer c2a12cd
+ * @ctx: The context from verify_sig_begin()
Josh Boyer c2a12cd
+ * @data: Data
Josh Boyer c2a12cd
+ * @datalen: The amount of @data
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This may be called multiple times.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+int verify_sig_add_data(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+			const void *data, size_t datalen)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	return ctx->add_data(ctx, data, datalen);
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(verify_sig_add_data);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * verify_sig_end - Finalise signature verification and return result
Josh Boyer c2a12cd
+ * @ctx: The context from verify_sig_begin()
Josh Boyer c2a12cd
+ * @sig: The signature data
Josh Boyer c2a12cd
+ * @siglen: The signature length
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+int verify_sig_end(struct crypto_key_verify_context *ctx,
Josh Boyer c2a12cd
+		   const void *sig, size_t siglen)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct crypto_key_parser *parser = ctx->parser;
Josh Boyer c2a12cd
+	int ret;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	ret = ctx->end(ctx, sig, siglen);
Josh Boyer c2a12cd
+	module_put(parser->owner);
Josh Boyer c2a12cd
+	return ret;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(verify_sig_end);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * verify_sig_end - Cancel signature verification
Josh Boyer c2a12cd
+ * @ctx: The context from verify_sig_begin()
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+void verify_sig_cancel(struct crypto_key_verify_context *ctx)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct crypto_key_parser *parser = ctx->parser;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	ctx->cancel(ctx);
Josh Boyer c2a12cd
+	module_put(parser->owner);
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(verify_sig_cancel);
Josh Boyer c2a12cd
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Josh Boyer c115215
From a0fe6700fba7b7497cf137dc6a969d299ee59c67 Mon Sep 17 00:00:00 2001
Josh Boyer c2a12cd
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 13:59:52 +0100
Josh Boyer c115215
Subject: [PATCH 04/28] KEYS: Asymmetric public-key algorithm crypto key
Josh Boyer 3dd0fcf
 subtype
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Add a subtype for supporting asymmetric public-key encryption algorithms such
Josh Boyer c2a12cd
as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337).
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c2a12cd
---
Josh Boyer 306dfcc
 security/keys/crypto/Kconfig      |  10 ++++
Josh Boyer 306dfcc
 security/keys/crypto/Makefile     |   3 +-
Josh Boyer 306dfcc
 security/keys/crypto/public_key.c |  55 ++++++++++++++++++++
Josh Boyer 306dfcc
 security/keys/crypto/public_key.h | 106 ++++++++++++++++++++++++++++++++++++++
Josh Boyer 3dd0fcf
 4 files changed, 173 insertions(+), 1 deletion(-)
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/public_key.c
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/public_key.h
Josh Boyer 3dd0fcf
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
index 3d15710..5f2b8ac 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
@@ -5,3 +5,13 @@ config CRYPTO_KEY_TYPE
Josh Boyer c2a12cd
 	  This option provides support for a type of key that holds the keys
Josh Boyer c2a12cd
 	  required for cryptographic operations such as encryption, decryption,
Josh Boyer c2a12cd
 	  signature generation and signature verification.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
Josh Boyer c2a12cd
+	tristate "Asymmetric public-key crypto algorithm subtype"
Josh Boyer c2a12cd
+	depends on CRYPTO_KEY_TYPE
Josh Boyer 3dd0fcf
+	select MPILIB
Josh Boyer c2a12cd
+	help
Josh Boyer c2a12cd
+	  This option provides support for asymmetric public key type handling.
Josh Boyer c2a12cd
+	  If signature generation and/or verification are to be used,
Josh Boyer c2a12cd
+	  appropriate hash algorithms (such as SHA-1) must be available.
Josh Boyer c2a12cd
+	  ENOPKG will be reported if the requisite algorithm is unavailable.
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
index 67001bc..6384306 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
@@ -3,5 +3,6 @@
Josh Boyer 3dd0fcf
 #
Josh Boyer c2a12cd
 
Josh Boyer 3dd0fcf
 obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
Josh Boyer 3dd0fcf
-
Josh Boyer c2a12cd
 crypto_keys-y := crypto_type.o crypto_verify.o
Josh Boyer 3dd0fcf
+
Josh Boyer 3dd0fcf
+obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/public_key.c b/security/keys/crypto/public_key.c
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer c2a12cd
index 0000000..c00ddac
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/public_key.c
Josh Boyer c2a12cd
@@ -0,0 +1,55 @@
Josh Boyer c2a12cd
+/* Asymmetric public key crypto subtype
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#define pr_fmt(fmt) "PKEY: "fmt
Josh Boyer c2a12cd
+#include <linux/module.h>
Josh Boyer c2a12cd
+#include <linux/kernel.h>
Josh Boyer c2a12cd
+#include "public_key.h"
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+MODULE_LICENSE("GPL");
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Provide a part of a description of the key for /proc/keys.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static void public_key_describe(const struct key *crypto_key,
Josh Boyer c2a12cd
+				struct seq_file *m)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct public_key *key = crypto_key->payload.data;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (key)
Josh Boyer c2a12cd
+		seq_puts(m, key->algo->name);
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Destroy a public key algorithm key
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static void public_key_destroy(void *payload)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct public_key *key = payload;
Josh Boyer c2a12cd
+	int i;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (key) {
Josh Boyer c2a12cd
+		for (i = 0; i < ARRAY_SIZE(key->mpi); i++)
Josh Boyer c2a12cd
+			mpi_free(key->mpi[i]);
Josh Boyer c2a12cd
+		kfree(key);
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Public key algorithm crypto key subtype
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+struct crypto_key_subtype public_key_crypto_key_subtype = {
Josh Boyer c2a12cd
+	.owner		= THIS_MODULE,
Josh Boyer c2a12cd
+	.name		= "public_key",
Josh Boyer c2a12cd
+	.describe	= public_key_describe,
Josh Boyer c2a12cd
+	.destroy	= public_key_destroy,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(public_key_crypto_key_subtype);
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer c2a12cd
index 0000000..81ed603
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/public_key.h
Josh Boyer c2a12cd
@@ -0,0 +1,106 @@
Josh Boyer c2a12cd
+/* Asymmetric public-key algorithm definitions
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#ifndef _LINUX_PUBLIC_KEY_H
Josh Boyer c2a12cd
+#define _LINUX_PUBLIC_KEY_H
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#include <linux/mpi.h>
Josh Boyer c2a12cd
+#include <crypto/hash.h>
Josh Boyer c2a12cd
+#include <keys/crypto-subtype.h>
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct public_key;
Josh Boyer c2a12cd
+struct public_key_signature;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+enum pkey_hash_algo {
Josh Boyer c2a12cd
+	PKEY_HASH_MD5,
Josh Boyer c2a12cd
+	PKEY_HASH_SHA1,
Josh Boyer c2a12cd
+	PKEY_HASH_RIPE_MD_160,
Josh Boyer c2a12cd
+	PKEY_HASH_SHA256,
Josh Boyer c2a12cd
+	PKEY_HASH_SHA384,
Josh Boyer c2a12cd
+	PKEY_HASH_SHA512,
Josh Boyer c2a12cd
+	PKEY_HASH_SHA224,
Josh Boyer c2a12cd
+	PKEY_HASH__LAST
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Public key type definition
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+struct public_key_algorithm {
Josh Boyer c2a12cd
+	const char	*name;
Josh Boyer c2a12cd
+	u8		n_pub_mpi;	/* Number of MPIs in public key */
Josh Boyer c2a12cd
+	u8		n_sec_mpi;	/* Number of MPIs in secret key */
Josh Boyer c2a12cd
+	u8		n_sig_mpi;	/* Number of MPIs in a signature */
Josh Boyer c2a12cd
+	int (*verify)(const struct public_key *key,
Josh Boyer c2a12cd
+		      const struct public_key_signature *sig);
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Asymmetric public key data
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+struct public_key {
Josh Boyer c2a12cd
+	const struct public_key_algorithm *algo;
Josh Boyer c2a12cd
+	u8	capabilities;
Josh Boyer c2a12cd
+#define PKEY_CAN_ENCRYPT	0x01
Josh Boyer c2a12cd
+#define PKEY_CAN_DECRYPT	0x02
Josh Boyer c2a12cd
+#define PKEY_CAN_ENCDEC		(PKEY_CAN_ENCRYPT | PKEY_CAN_DECRYPT)
Josh Boyer c2a12cd
+#define PKEY_CAN_SIGN		0x04
Josh Boyer c2a12cd
+#define PKEY_CAN_VERIFY		0x08
Josh Boyer c2a12cd
+#define PKEY_CAN_SIGVER		(PKEY_CAN_SIGN | PKEY_CAN_VERIFY)
Josh Boyer c2a12cd
+	union {
Josh Boyer c2a12cd
+		MPI	mpi[5];
Josh Boyer c2a12cd
+		struct {
Josh Boyer c2a12cd
+			MPI	p;	/* DSA prime */
Josh Boyer c2a12cd
+			MPI	q;	/* DSA group order */
Josh Boyer c2a12cd
+			MPI	g;	/* DSA group generator */
Josh Boyer c2a12cd
+			MPI	y;	/* DSA public-key value = g^x mod p */
Josh Boyer c2a12cd
+			MPI	x;	/* DSA secret exponent (if present) */
Josh Boyer c2a12cd
+		} dsa;
Josh Boyer c2a12cd
+		struct {
Josh Boyer c2a12cd
+			MPI	n;	/* RSA public modulus */
Josh Boyer c2a12cd
+			MPI	e;	/* RSA public encryption exponent */
Josh Boyer c2a12cd
+			MPI	d;	/* RSA secret encryption exponent (if present) */
Josh Boyer c2a12cd
+			MPI	p;	/* RSA secret prime (if present) */
Josh Boyer c2a12cd
+			MPI	q;	/* RSA secret prime (if present) */
Josh Boyer c2a12cd
+		} rsa;
Josh Boyer c2a12cd
+	};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	u8	key_id[8];	/* ID of this key pair */
Josh Boyer c2a12cd
+	u8	key_id_size;	/* Number of bytes in key_id */
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Asymmetric public key algorithm signature data
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+struct public_key_signature {
Josh Boyer c2a12cd
+	struct crypto_key_verify_context base;
Josh Boyer c2a12cd
+	u8 *digest;
Josh Boyer c2a12cd
+	enum pkey_hash_algo pkey_hash_algo : 8;
Josh Boyer c2a12cd
+	u8 signed_hash_msw[2];
Josh Boyer c2a12cd
+	u8 digest_size;	/* Number of bytes in digest */
Josh Boyer c2a12cd
+	union {
Josh Boyer c2a12cd
+		MPI mpi[2];
Josh Boyer c2a12cd
+		struct {
Josh Boyer c2a12cd
+			MPI s;			/* m^d mod n */
Josh Boyer c2a12cd
+		} rsa;
Josh Boyer c2a12cd
+		struct {
Josh Boyer c2a12cd
+			MPI r;
Josh Boyer c2a12cd
+			MPI s;
Josh Boyer c2a12cd
+		} dsa;
Josh Boyer c2a12cd
+	};
Josh Boyer c2a12cd
+	struct shash_desc hash;			/* This must go last! */
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern struct crypto_key_verify_context *pgp_pkey_verify_sig_begin(
Josh Boyer c2a12cd
+	struct key *crypto_key, const u8 *sigdata, size_t siglen);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern struct crypto_key_subtype public_key_crypto_key_subtype;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#endif /* _LINUX_PUBLIC_KEY_H */
Josh Boyer c2a12cd
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer 5a0e7f0
Josh Boyer 5a0e7f0
Josh Boyer c115215
From 39eaf7c28e0ca07dcb5e1e2a12db62815890f0e7 Mon Sep 17 00:00:00 2001
Josh Boyer 5a0e7f0
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 14:10:37 +0100
Josh Boyer c115215
Subject: [PATCH 05/28] MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA
Josh Boyer 306dfcc
 signature verification
Josh Boyer 5a0e7f0
Josh Boyer 306dfcc
Reinstate and export mpi_cmp() and mpi_cmp_ui() from the MPI library for use by
Josh Boyer 306dfcc
RSA signature verification as per RFC3447 section 5.2.2 step 1.
Josh Boyer 5a0e7f0
Josh Boyer 5a0e7f0
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer 5a0e7f0
---
Josh Boyer 306dfcc
 lib/mpi/Makefile  |  1 +
Josh Boyer 306dfcc
 lib/mpi/mpi-cmp.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
Josh Boyer 306dfcc
 2 files changed, 71 insertions(+)
Josh Boyer 306dfcc
 create mode 100644 lib/mpi/mpi-cmp.c
Josh Boyer 306dfcc
Josh Boyer 306dfcc
diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile
Josh Boyer 306dfcc
index 45ca90a..019a68c 100644
Josh Boyer 306dfcc
--- a/lib/mpi/Makefile
Josh Boyer 306dfcc
+++ b/lib/mpi/Makefile
Josh Boyer 306dfcc
@@ -14,6 +14,7 @@ mpi-y = \
Josh Boyer 306dfcc
 	generic_mpih-add1.o		\
Josh Boyer 306dfcc
 	mpicoder.o			\
Josh Boyer 306dfcc
 	mpi-bit.o			\
Josh Boyer 306dfcc
+	mpi-cmp.o			\
Josh Boyer 306dfcc
 	mpih-cmp.o			\
Josh Boyer 306dfcc
 	mpih-div.o			\
Josh Boyer 306dfcc
 	mpih-mul.o			\
Josh Boyer 5a0e7f0
diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c
Josh Boyer 306dfcc
new file mode 100644
Josh Boyer 306dfcc
index 0000000..1871e7b
Josh Boyer 306dfcc
--- /dev/null
Josh Boyer 5a0e7f0
+++ b/lib/mpi/mpi-cmp.c
Josh Boyer 306dfcc
@@ -0,0 +1,70 @@
Josh Boyer 306dfcc
+/* mpi-cmp.c  -  MPI functions
Josh Boyer 306dfcc
+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
Josh Boyer 306dfcc
+ *
Josh Boyer 306dfcc
+ * This file is part of GnuPG.
Josh Boyer 306dfcc
+ *
Josh Boyer 306dfcc
+ * GnuPG is free software; you can redistribute it and/or modify
Josh Boyer 306dfcc
+ * it under the terms of the GNU General Public License as published by
Josh Boyer 306dfcc
+ * the Free Software Foundation; either version 2 of the License, or
Josh Boyer 306dfcc
+ * (at your option) any later version.
Josh Boyer 306dfcc
+ *
Josh Boyer 306dfcc
+ * GnuPG is distributed in the hope that it will be useful,
Josh Boyer 306dfcc
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
Josh Boyer 306dfcc
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Josh Boyer 306dfcc
+ * GNU General Public License for more details.
Josh Boyer 306dfcc
+ *
Josh Boyer 306dfcc
+ * You should have received a copy of the GNU General Public License
Josh Boyer 306dfcc
+ * along with this program; if not, write to the Free Software
Josh Boyer 306dfcc
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Josh Boyer 306dfcc
+ */
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+#include "mpi-internal.h"
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+int mpi_cmp_ui(MPI u, unsigned long v)
Josh Boyer 306dfcc
+{
Josh Boyer 306dfcc
+	mpi_limb_t limb = v;
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	mpi_normalize(u);
Josh Boyer 306dfcc
+	if (!u->nlimbs && !limb)
Josh Boyer 306dfcc
+		return 0;
Josh Boyer 306dfcc
+	if (u->sign)
Josh Boyer 306dfcc
+		return -1;
Josh Boyer 306dfcc
+	if (u->nlimbs > 1)
Josh Boyer 306dfcc
+		return 1;
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	if (u->d[0] == limb)
Josh Boyer 306dfcc
+		return 0;
Josh Boyer 306dfcc
+	else if (u->d[0] > limb)
Josh Boyer 306dfcc
+		return 1;
Josh Boyer 306dfcc
+	else
Josh Boyer 306dfcc
+		return -1;
Josh Boyer 306dfcc
+}
Josh Boyer 5a0e7f0
+EXPORT_SYMBOL_GPL(mpi_cmp_ui);
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+int mpi_cmp(MPI u, MPI v)
Josh Boyer 306dfcc
+{
Josh Boyer 306dfcc
+	mpi_size_t usize, vsize;
Josh Boyer 306dfcc
+	int cmp;
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	mpi_normalize(u);
Josh Boyer 306dfcc
+	mpi_normalize(v);
Josh Boyer 306dfcc
+	usize = u->nlimbs;
Josh Boyer 306dfcc
+	vsize = v->nlimbs;
Josh Boyer 306dfcc
+	if (!u->sign && v->sign)
Josh Boyer 306dfcc
+		return 1;
Josh Boyer 306dfcc
+	if (u->sign && !v->sign)
Josh Boyer 306dfcc
+		return -1;
Josh Boyer 306dfcc
+	if (usize != vsize && !u->sign && !v->sign)
Josh Boyer 306dfcc
+		return usize - vsize;
Josh Boyer 306dfcc
+	if (usize != vsize && u->sign && v->sign)
Josh Boyer 306dfcc
+		return vsize + usize;
Josh Boyer 306dfcc
+	if (!usize)
Josh Boyer 306dfcc
+		return 0;
Josh Boyer 306dfcc
+	cmp = mpihelp_cmp(u->d, v->d, usize);
Josh Boyer 306dfcc
+	if (!cmp)
Josh Boyer 306dfcc
+		return 0;
Josh Boyer 306dfcc
+	if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0))
Josh Boyer 306dfcc
+		return 1;
Josh Boyer 306dfcc
+	return -1;
Josh Boyer 306dfcc
+}
Josh Boyer 5a0e7f0
+EXPORT_SYMBOL_GPL(mpi_cmp);
Josh Boyer 5a0e7f0
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Josh Boyer c115215
From c995ac0765cfffe9b293327717e080c2cd253779 Mon Sep 17 00:00:00 2001
Josh Boyer c2a12cd
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 14:10:39 +0100
Josh Boyer c115215
Subject: [PATCH 06/28] KEYS: RSA: Implement signature verification algorithm
Josh Boyer 5a0e7f0
 [PKCS#1 / RFC3447]
Josh Boyer c2a12cd
Josh Boyer 5a0e7f0
Implement RSA public key cryptography [PKCS#1 / RFC3447].  At this time, only
Josh Boyer 5a0e7f0
the signature verification algorithm is supported.  This uses the asymmetric
Josh Boyer 5a0e7f0
public key subtype to hold its key data.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c2a12cd
---
Josh Boyer 306dfcc
 security/keys/crypto/Kconfig      |   7 +
Josh Boyer 306dfcc
 security/keys/crypto/Makefile     |   1 +
Josh Boyer 306dfcc
 security/keys/crypto/crypto_rsa.c | 264 ++++++++++++++++++++++++++++++++++++++
Josh Boyer 306dfcc
 security/keys/crypto/public_key.h |   2 +
Josh Boyer 5a0e7f0
 4 files changed, 274 insertions(+)
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/crypto_rsa.c
Josh Boyer 3dd0fcf
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
index 5f2b8ac..4e3777e 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
@@ -15,3 +15,10 @@ config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
Josh Boyer c2a12cd
 	  If signature generation and/or verification are to be used,
Josh Boyer c2a12cd
 	  appropriate hash algorithms (such as SHA-1) must be available.
Josh Boyer c2a12cd
 	  ENOPKG will be reported if the requisite algorithm is unavailable.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+config CRYPTO_KEY_PKEY_ALGO_RSA
Josh Boyer c2a12cd
+	tristate "RSA public-key algorithm"
Josh Boyer c2a12cd
+	depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
Josh Boyer 3dd0fcf
+	select MPILIB_EXTRA
Josh Boyer c2a12cd
+	help
Josh Boyer c2a12cd
+	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
index 6384306..b6b1a5a 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
@@ -6,3 +6,4 @@ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o
Josh Boyer 3dd0fcf
 crypto_keys-y := crypto_type.o crypto_verify.o
Josh Boyer 3dd0fcf
 
Josh Boyer c2a12cd
 obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
Josh Boyer c2a12cd
+obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer 5a0e7f0
index 0000000..845285c
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/crypto_rsa.c
Josh Boyer 5a0e7f0
@@ -0,0 +1,264 @@
Josh Boyer c2a12cd
+/* RSA asymmetric public-key algorithm [RFC3447]
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#define pr_fmt(fmt) "RSA: "fmt
Josh Boyer c2a12cd
+#include <linux/module.h>
Josh Boyer c2a12cd
+#include <linux/kernel.h>
Josh Boyer c2a12cd
+#include "public_key.h"
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+MODULE_LICENSE("GPL");
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#define kenter(FMT, ...) \
Josh Boyer c2a12cd
+	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
Josh Boyer c2a12cd
+#define kleave(FMT, ...) \
Josh Boyer c2a12cd
+	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static const u8 RSA_digest_info_MD5[] = {
Josh Boyer c2a12cd
+	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
Josh Boyer c2a12cd
+	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
Josh Boyer c2a12cd
+	0x05, 0x00, 0x04, 0x10
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static const u8 RSA_digest_info_SHA1[] = {
Josh Boyer c2a12cd
+	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
Josh Boyer c2a12cd
+	0x2B, 0x0E, 0x03, 0x02, 0x1A,
Josh Boyer c2a12cd
+	0x05, 0x00, 0x04, 0x14
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static const u8 RSA_digest_info_RIPE_MD_160[] = {
Josh Boyer c2a12cd
+	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
Josh Boyer c2a12cd
+	0x2B, 0x24, 0x03, 0x02, 0x01,
Josh Boyer c2a12cd
+	0x05, 0x00, 0x04, 0x14
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static const u8 RSA_digest_info_SHA224[] = {
Josh Boyer c2a12cd
+	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
Josh Boyer c2a12cd
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
Josh Boyer c2a12cd
+	0x05, 0x00, 0x04, 0x1C
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static const u8 RSA_digest_info_SHA256[] = {
Josh Boyer c2a12cd
+	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
Josh Boyer c2a12cd
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
Josh Boyer c2a12cd
+	0x05, 0x00, 0x04, 0x20
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static const u8 RSA_digest_info_SHA384[] = {
Josh Boyer c2a12cd
+	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
Josh Boyer c2a12cd
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
Josh Boyer c2a12cd
+	0x05, 0x00, 0x04, 0x30
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static const u8 RSA_digest_info_SHA512[] = {
Josh Boyer c2a12cd
+	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
Josh Boyer c2a12cd
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
Josh Boyer c2a12cd
+	0x05, 0x00, 0x04, 0x40
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static const struct {
Josh Boyer 5a0e7f0
+	const u8 *data;
Josh Boyer c2a12cd
+	size_t size;
Josh Boyer c2a12cd
+} RSA_ASN1_templates[PKEY_HASH__LAST] = {
Josh Boyer c2a12cd
+#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
Josh Boyer c2a12cd
+	[PKEY_HASH_MD5]		= _(MD5),
Josh Boyer c2a12cd
+	[PKEY_HASH_SHA1]	= _(SHA1),
Josh Boyer c2a12cd
+	[PKEY_HASH_RIPE_MD_160]	= _(RIPE_MD_160),
Josh Boyer c2a12cd
+	[PKEY_HASH_SHA256]	= _(SHA256),
Josh Boyer c2a12cd
+	[PKEY_HASH_SHA384]	= _(SHA384),
Josh Boyer c2a12cd
+	[PKEY_HASH_SHA512]	= _(SHA512),
Josh Boyer c2a12cd
+	[PKEY_HASH_SHA224]	= _(SHA224),
Josh Boyer c2a12cd
+#undef _
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * RSAVP1() function [RFC3447 sec 5.2.2]
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int RSAVP1(const struct public_key *key, MPI s, MPI *_m)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	MPI m;
Josh Boyer c2a12cd
+	int ret;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* (1) Validate 0 <= s < n */
Josh Boyer c2a12cd
+	if (mpi_cmp_ui(s, 0) < 0) {
Josh Boyer c2a12cd
+		kleave(" = -EBADMSG [s < 0]");
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+	if (mpi_cmp(s, key->rsa.n) >= 0) {
Josh Boyer c2a12cd
+		kleave(" = -EBADMSG [s >= n]");
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	m = mpi_alloc(0);
Josh Boyer c2a12cd
+	if (!m)
Josh Boyer c2a12cd
+		return -ENOMEM;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* (2) m = s^e mod n */
Josh Boyer c2a12cd
+	ret = mpi_powm(m, s, key->rsa.e, key->rsa.n);
Josh Boyer c2a12cd
+	if (ret < 0) {
Josh Boyer c2a12cd
+		mpi_free(m);
Josh Boyer c2a12cd
+		return ret;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	*_m = m;
Josh Boyer c2a12cd
+	return 0;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Integer to Octet String conversion [RFC3447 sec 4.1]
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	unsigned X_size, x_size;
Josh Boyer c2a12cd
+	int X_sign;
Josh Boyer c2a12cd
+	u8 *X;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* Make sure the string is the right length.  The number should begin
Josh Boyer c2a12cd
+	 * with { 0x00, 0x01, ... } so we have to account for 15 leading zero
Josh Boyer c2a12cd
+	 * bits not being reported by MPI.
Josh Boyer c2a12cd
+	 */
Josh Boyer c2a12cd
+	x_size = mpi_get_nbits(x);
Josh Boyer c2a12cd
+	pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8);
Josh Boyer c2a12cd
+	if (x_size != xLen * 8 - 15)
Josh Boyer c2a12cd
+		return -ERANGE;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	X = mpi_get_buffer(x, &X_size, &X_sign);
Josh Boyer c2a12cd
+	if (!X)
Josh Boyer c2a12cd
+		return -ENOMEM;
Josh Boyer c2a12cd
+	if (X_sign < 0) {
Josh Boyer c2a12cd
+		kfree(X);
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+	if (X_size != xLen - 1) {
Josh Boyer c2a12cd
+		kfree(X);
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	*_X = X;
Josh Boyer c2a12cd
+	return 0;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Perform the RSA signature verification.
Josh Boyer c2a12cd
+ * @H: Value of hash of data and metadata
Josh Boyer c2a12cd
+ * @EM: The computed signature value
Josh Boyer c2a12cd
+ * @k: The size of EM (EM[0] is an invalid location but should hold 0x00)
Josh Boyer c2a12cd
+ * @hash_size: The size of H
Josh Boyer c2a12cd
+ * @asn1_template: The DigestInfo ASN.1 template
Josh Boyer c2a12cd
+ * @asn1_size: Size of asm1_template[]
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
Josh Boyer c2a12cd
+		      const u8 *asn1_template, size_t asn1_size)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	unsigned PS_end, T_offset, i;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (k < 2 + 1 + asn1_size + hash_size)
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* Decode the EMSA-PKCS1-v1_5 */
Josh Boyer c2a12cd
+	if (EM[1] != 0x01) {
Josh Boyer c2a12cd
+		kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]);
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	T_offset = k - (asn1_size + hash_size);
Josh Boyer c2a12cd
+	PS_end = T_offset - 1;
Josh Boyer c2a12cd
+	if (EM[PS_end] != 0x00) {
Josh Boyer c2a12cd
+		kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]);
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	for (i = 2; i < PS_end; i++) {
Josh Boyer c2a12cd
+		if (EM[i] != 0xff) {
Josh Boyer c2a12cd
+			kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]);
Josh Boyer c2a12cd
+			return -EBADMSG;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) {
Josh Boyer c2a12cd
+		kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) {
Josh Boyer c2a12cd
+		kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
Josh Boyer c2a12cd
+		return -EKEYREJECTED;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	kleave(" = 0");
Josh Boyer c2a12cd
+	return 0;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Perform the verification step [RFC3447 sec 8.2.2].
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int RSA_verify_signature(const struct public_key *key,
Josh Boyer c2a12cd
+				const struct public_key_signature *sig)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	size_t tsize;
Josh Boyer c2a12cd
+	int ret;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* Variables as per RFC3447 sec 8.2.2 */
Josh Boyer c2a12cd
+	const u8 *H = sig->digest;
Josh Boyer c2a12cd
+	u8 *EM = NULL;
Josh Boyer c2a12cd
+	MPI m = NULL;
Josh Boyer c2a12cd
+	size_t k;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	kenter("");
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* (1) Check the signature size against the public key modulus size */
Josh Boyer c2a12cd
+	k = (mpi_get_nbits(key->rsa.n) + 7) / 8;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8;
Josh Boyer c2a12cd
+	pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize);
Josh Boyer c2a12cd
+	if (tsize != k) {
Josh Boyer c2a12cd
+		ret = -EBADMSG;
Josh Boyer c2a12cd
+		goto error;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* (2b) Apply the RSAVP1 verification primitive to the public key */
Josh Boyer c2a12cd
+	ret = RSAVP1(key, sig->rsa.s, &m);
Josh Boyer c2a12cd
+	if (ret < 0)
Josh Boyer c2a12cd
+		goto error;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* (2c) Convert the message representative (m) to an encoded message
Josh Boyer c2a12cd
+	 *      (EM) of length k octets.
Josh Boyer c2a12cd
+	 *
Josh Boyer c2a12cd
+	 *      NOTE!  The leading zero byte is suppressed by MPI, so we pass a
Josh Boyer c2a12cd
+	 *      pointer to the _preceding_ byte to RSA_verify()!
Josh Boyer c2a12cd
+	 */
Josh Boyer c2a12cd
+	ret = RSA_I2OSP(m, k, &EM;;
Josh Boyer c2a12cd
+	if (ret < 0)
Josh Boyer c2a12cd
+		goto error;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	ret = RSA_verify(H, EM - 1, k, sig->digest_size,
Josh Boyer c2a12cd
+			 RSA_ASN1_templates[sig->pkey_hash_algo].data,
Josh Boyer c2a12cd
+			 RSA_ASN1_templates[sig->pkey_hash_algo].size);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+error:
Josh Boyer c2a12cd
+	kfree(EM);
Josh Boyer c2a12cd
+	mpi_free(m);
Josh Boyer c2a12cd
+	kleave(" = %d", ret);
Josh Boyer c2a12cd
+	return ret;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+const struct public_key_algorithm RSA_public_key_algorithm = {
Josh Boyer c2a12cd
+	.name		= "RSA",
Josh Boyer c2a12cd
+	.n_pub_mpi	= 2,
Josh Boyer c2a12cd
+	.n_sec_mpi	= 3,
Josh Boyer c2a12cd
+	.n_sig_mpi	= 1,
Josh Boyer c2a12cd
+	.verify		= RSA_verify_signature,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(RSA_public_key_algorithm);
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h
Josh Boyer c2a12cd
index 81ed603..7913615 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/public_key.h
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/public_key.h
Josh Boyer c2a12cd
@@ -42,6 +42,8 @@ struct public_key_algorithm {
Josh Boyer c2a12cd
 		      const struct public_key_signature *sig);
Josh Boyer c2a12cd
 };
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
+extern const struct public_key_algorithm RSA_public_key_algorithm;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
 /*
Josh Boyer c2a12cd
  * Asymmetric public key data
Josh Boyer c2a12cd
  */
Josh Boyer c2a12cd
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer 3dd0fcf
Josh Boyer 3dd0fcf
Josh Boyer c115215
From d9acf3806acdc9ab5e26a1c604989070a7ae6840 Mon Sep 17 00:00:00 2001
Josh Boyer 3dd0fcf
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 14:11:19 +0100
Josh Boyer c115215
Subject: [PATCH 07/28] KEYS: RSA: Fix signature verification for shorter
Josh Boyer 5a0e7f0
 signatures
Josh Boyer 3dd0fcf
Josh Boyer 3dd0fcf
gpg can produce a signature file where length of signature is less than the
Josh Boyer 3dd0fcf
modulus size because the amount of space an MPI takes up is kept as low as
Josh Boyer 3dd0fcf
possible by discarding leading zeros.  This regularly happens for several
Josh Boyer 3dd0fcf
modules during the build.
Josh Boyer 3dd0fcf
Josh Boyer 3dd0fcf
Fix it by relaxing check in RSA verification code.
Josh Boyer 3dd0fcf
Josh Boyer 3dd0fcf
Thanks to Tomas Mraz and Miloslav Trmac for help.
Josh Boyer 3dd0fcf
Josh Boyer 3dd0fcf
Signed-off-by: Milan Broz <mbroz@redhat.com>
Josh Boyer 3dd0fcf
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer 3dd0fcf
---
Josh Boyer 306dfcc
 security/keys/crypto/crypto_rsa.c | 14 +++++++++++---
Josh Boyer 3dd0fcf
 1 file changed, 11 insertions(+), 3 deletions(-)
Josh Boyer 3dd0fcf
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c
Josh Boyer 5a0e7f0
index 845285c..a4a63be 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/crypto_rsa.c
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/crypto_rsa.c
Josh Boyer 3dd0fcf
@@ -219,15 +219,23 @@ static int RSA_verify_signature(const struct public_key *key,
Josh Boyer 3dd0fcf
 	kenter("");
Josh Boyer 3dd0fcf
 
Josh Boyer 3dd0fcf
 	/* (1) Check the signature size against the public key modulus size */
Josh Boyer 3dd0fcf
-	k = (mpi_get_nbits(key->rsa.n) + 7) / 8;
Josh Boyer 3dd0fcf
+	k = mpi_get_nbits(key->rsa.n);
Josh Boyer 3dd0fcf
+	tsize = mpi_get_nbits(sig->rsa.s);
Josh Boyer 3dd0fcf
 
Josh Boyer 3dd0fcf
-	tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8;
Josh Boyer 3dd0fcf
+	/* According to RFC 4880 sec 3.2, length of MPI is computed starting
Josh Boyer 3dd0fcf
+	 * from most significant bit.  So the RFC 3447 sec 8.2.2 size check
Josh Boyer 3dd0fcf
+	 * must be relaxed to conform with shorter signatures - so we fail here
Josh Boyer 3dd0fcf
+	 * only if signature length is longer than modulus size.
Josh Boyer 3dd0fcf
+	 */
Josh Boyer 3dd0fcf
 	pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize);
Josh Boyer 3dd0fcf
-	if (tsize != k) {
Josh Boyer 3dd0fcf
+	if (k < tsize) {
Josh Boyer 3dd0fcf
 		ret = -EBADMSG;
Josh Boyer 3dd0fcf
 		goto error;
Josh Boyer 3dd0fcf
 	}
Josh Boyer 3dd0fcf
 
Josh Boyer 3dd0fcf
+	/* Round up and convert to octets */
Josh Boyer 3dd0fcf
+	k = (k + 7) / 8;
Josh Boyer 3dd0fcf
+
Josh Boyer 3dd0fcf
 	/* (2b) Apply the RSAVP1 verification primitive to the public key */
Josh Boyer 3dd0fcf
 	ret = RSAVP1(key, sig->rsa.s, &m);
Josh Boyer 3dd0fcf
 	if (ret < 0)
Josh Boyer 3dd0fcf
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Josh Boyer c115215
From 9a2a2b1faa27be883b3aa2c47bbc367bd1a1f653 Mon Sep 17 00:00:00 2001
Josh Boyer c2a12cd
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 14:11:19 +0100
Josh Boyer c115215
Subject: [PATCH 08/28] PGPLIB: PGP definitions (RFC 4880)
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Provide some useful PGP definitions from RFC 4880.  These describe details of
Josh Boyer c2a12cd
public key crypto as used by crypto keys for things like signature
Josh Boyer c2a12cd
verification.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c2a12cd
---
Josh Boyer 306dfcc
 include/linux/pgp.h | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++
Josh Boyer 3dd0fcf
 1 file changed, 206 insertions(+)
Josh Boyer c2a12cd
 create mode 100644 include/linux/pgp.h
Josh Boyer c2a12cd
Josh Boyer c2a12cd
diff --git a/include/linux/pgp.h b/include/linux/pgp.h
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer c2a12cd
index 0000000..1359f64
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer c2a12cd
+++ b/include/linux/pgp.h
Josh Boyer c2a12cd
@@ -0,0 +1,206 @@
Josh Boyer c2a12cd
+/* PGP definitions (RFC 4880)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#ifndef _LINUX_PGP_H
Josh Boyer c2a12cd
+#define _LINUX_PGP_H
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#include <linux/types.h>
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_key_ID {
Josh Boyer c2a12cd
+	u8 id[8];
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_time {
Josh Boyer c2a12cd
+	u8 time[4];
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * PGP public-key algorithm identifiers [RFC4880: 9.1]
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+enum pgp_pubkey_algo {
Josh Boyer c2a12cd
+	PGP_PUBKEY_RSA_ENC_OR_SIG	= 1,
Josh Boyer c2a12cd
+	PGP_PUBKEY_RSA_ENC_ONLY		= 2,
Josh Boyer c2a12cd
+	PGP_PUBKEY_RSA_SIG_ONLY		= 3,
Josh Boyer c2a12cd
+	PGP_PUBKEY_ELGAMAL		= 16,
Josh Boyer c2a12cd
+	PGP_PUBKEY_DSA			= 17,
Josh Boyer c2a12cd
+	PGP_PUBKEY__LAST
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * PGP symmetric-key algorithm identifiers [RFC4880: 9.2]
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+enum pgp_symkey_algo {
Josh Boyer c2a12cd
+	PGP_SYMKEY_PLAINTEXT		= 0,
Josh Boyer c2a12cd
+	PGP_SYMKEY_IDEA			= 1,
Josh Boyer c2a12cd
+	PGP_SYMKEY_3DES			= 2,
Josh Boyer c2a12cd
+	PGP_SYMKEY_CAST5		= 3,
Josh Boyer c2a12cd
+	PGP_SYMKEY_BLOWFISH		= 4,
Josh Boyer c2a12cd
+	PGP_SYMKEY_AES_128KEY		= 7,
Josh Boyer c2a12cd
+	PGP_SYMKEY_AES_192KEY		= 8,
Josh Boyer c2a12cd
+	PGP_SYMKEY_AES_256KEY		= 9,
Josh Boyer c2a12cd
+	PGP_SYMKEY_TWOFISH_256KEY	= 10,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * PGP compression algorithm identifiers [RFC4880: 9.3]
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+enum pgp_compr_algo {
Josh Boyer c2a12cd
+	PGP_COMPR_UNCOMPRESSED		= 0,
Josh Boyer c2a12cd
+	PGP_COMPR_ZIP			= 1,
Josh Boyer c2a12cd
+	PGP_COMPR_ZLIB			= 2,
Josh Boyer c2a12cd
+	PGP_COMPR_BZIP2			= 3,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * PGP hash algorithm identifiers [RFC4880: 9.4]
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+enum pgp_hash_algo {
Josh Boyer c2a12cd
+	PGP_HASH_MD5			= 1,
Josh Boyer c2a12cd
+	PGP_HASH_SHA1			= 2,
Josh Boyer c2a12cd
+	PGP_HASH_RIPE_MD_160		= 3,
Josh Boyer c2a12cd
+	PGP_HASH_SHA256			= 8,
Josh Boyer c2a12cd
+	PGP_HASH_SHA384			= 9,
Josh Boyer c2a12cd
+	PGP_HASH_SHA512			= 10,
Josh Boyer c2a12cd
+	PGP_HASH_SHA224			= 11,
Josh Boyer c2a12cd
+	PGP_HASH__LAST
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern const char *const pgp_hash_algorithms[PGP_HASH__LAST];
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * PGP packet type tags [RFC4880: 4.3].
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+enum pgp_packet_tag {
Josh Boyer c2a12cd
+	PGP_PKT_RESERVED		= 0,
Josh Boyer c2a12cd
+	PGP_PKT_PUBKEY_ENC_SESSION_KEY	= 1,
Josh Boyer c2a12cd
+	PGP_PKT_SIGNATURE		= 2,
Josh Boyer c2a12cd
+	PGP_PKT_SYMKEY_ENC_SESSION_KEY	= 3,
Josh Boyer c2a12cd
+	PGP_PKT_ONEPASS_SIGNATURE	= 4,
Josh Boyer c2a12cd
+	PGP_PKT_SECRET_KEY		= 5,
Josh Boyer c2a12cd
+	PGP_PKT_PUBLIC_KEY		= 6,
Josh Boyer c2a12cd
+	PGP_PKT_SECRET_SUBKEY		= 7,
Josh Boyer c2a12cd
+	PGP_PKT_COMPRESSED_DATA		= 8,
Josh Boyer c2a12cd
+	PGP_PKT_SYM_ENC_DATA		= 9,
Josh Boyer c2a12cd
+	PGP_PKT_MARKER			= 10,
Josh Boyer c2a12cd
+	PGP_PKT_LITERAL_DATA		= 11,
Josh Boyer c2a12cd
+	PGP_PKT_TRUST			= 12,
Josh Boyer c2a12cd
+	PGP_PKT_USER_ID			= 13,
Josh Boyer c2a12cd
+	PGP_PKT_PUBLIC_SUBKEY		= 14,
Josh Boyer c2a12cd
+	PGP_PKT_USER_ATTRIBUTE		= 17,
Josh Boyer c2a12cd
+	PGP_PKT_SYM_ENC_AND_INTEG_DATA	= 18,
Josh Boyer c2a12cd
+	PGP_PKT_MODIFY_DETECT_CODE	= 19,
Josh Boyer c2a12cd
+	PGP_PKT_PRIVATE_0		= 60,
Josh Boyer c2a12cd
+	PGP_PKT_PRIVATE_3		= 63,
Josh Boyer c2a12cd
+	PGP_PKT__HIGHEST		= 63
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Signature (tag 2) packet [RFC4880: 5.2].
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+enum pgp_signature_version {
Josh Boyer c2a12cd
+	PGP_SIG_VERSION_3			= 3,
Josh Boyer c2a12cd
+	PGP_SIG_VERSION_4			= 4,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+enum pgp_signature_type {
Josh Boyer c2a12cd
+	PGP_SIG_BINARY_DOCUMENT_SIG		= 0x00,
Josh Boyer c2a12cd
+	PGP_SIG_CANONICAL_TEXT_DOCUMENT_SIG	= 0x01,
Josh Boyer c2a12cd
+	PGP_SIG_STANDALONE_SIG			= 0x02,
Josh Boyer c2a12cd
+	PGP_SIG_GENERAL_CERT_OF_UID_PUBKEY	= 0x10,
Josh Boyer c2a12cd
+	PGP_SIG_PERSONAL_CERT_OF_UID_PUBKEY	= 0x11,
Josh Boyer c2a12cd
+	PGP_SIG_CASUAL_CERT_OF_UID_PUBKEY	= 0x12,
Josh Boyer c2a12cd
+	PGP_SIG_POSTITIVE_CERT_OF_UID_PUBKEY	= 0x13,
Josh Boyer c2a12cd
+	PGP_SIG_SUBKEY_BINDING_SIG		= 0x18,
Josh Boyer c2a12cd
+	PGP_SIG_PRIMARY_KEY_BINDING_SIG		= 0x19,
Josh Boyer c2a12cd
+	PGP_SIG_DIRECTLY_ON_KEY			= 0x1F,
Josh Boyer c2a12cd
+	PGP_SIG_KEY_REVOCATION_SIG		= 0x20,
Josh Boyer c2a12cd
+	PGP_SIG_SUBKEY_REVOCATION_SIG		= 0x28,
Josh Boyer c2a12cd
+	PGP_SIG_CERT_REVOCATION_SIG		= 0x30,
Josh Boyer c2a12cd
+	PGP_SIG_TIMESTAMP_SIG			= 0x40,
Josh Boyer c2a12cd
+	PGP_SIG_THIRD_PARTY_CONFIRM_SIG		= 0x50,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_signature_v3_packet {
Josh Boyer c2a12cd
+	enum pgp_signature_version version : 8; /* == PGP_SIG_VERSION_3 */
Josh Boyer c2a12cd
+	u8	length_of_hashed;	/* == 5 */
Josh Boyer c2a12cd
+	struct {
Josh Boyer c2a12cd
+		enum pgp_signature_type signature_type : 8;
Josh Boyer c2a12cd
+		struct pgp_time	creation_time;
Josh Boyer c2a12cd
+	} hashed;
Josh Boyer c2a12cd
+	struct pgp_key_ID issuer;
Josh Boyer c2a12cd
+	enum pgp_pubkey_algo pubkey_algo : 8;
Josh Boyer c2a12cd
+	enum pgp_hash_algo hash_algo : 8;
Josh Boyer c2a12cd
+} __packed;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_signature_v4_packet {
Josh Boyer c2a12cd
+	enum pgp_signature_version version : 8;	/* == PGP_SIG_VERSION_4 */
Josh Boyer c2a12cd
+	enum pgp_signature_type signature_type : 8;
Josh Boyer c2a12cd
+	enum pgp_pubkey_algo pubkey_algo : 8;
Josh Boyer c2a12cd
+	enum pgp_hash_algo hash_algo : 8;
Josh Boyer c2a12cd
+} __packed;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * V4 signature subpacket types [RFC4880: 5.2.3.1].
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+enum pgp_sig_subpkt_type {
Josh Boyer c2a12cd
+	PGP_SIG_CREATION_TIME			= 2,
Josh Boyer c2a12cd
+	PGP_SIG_EXPIRATION_TIME			= 3,
Josh Boyer c2a12cd
+	PGP_SIG_EXPORTABLE_CERT			= 4,
Josh Boyer c2a12cd
+	PGP_SIG_TRUST_SIG			= 5,
Josh Boyer c2a12cd
+	PGP_SIG_REGEXP				= 6,
Josh Boyer c2a12cd
+	PGP_SIG_REVOCABLE			= 7,
Josh Boyer c2a12cd
+	PGP_SIG_KEY_EXPIRATION_TIME		= 9,
Josh Boyer c2a12cd
+	PGP_SIG_PREF_SYM_ALGO			= 11,
Josh Boyer c2a12cd
+	PGP_SIG_REVOCATION_KEY			= 12,
Josh Boyer c2a12cd
+	PGP_SIG_ISSUER				= 16,
Josh Boyer c2a12cd
+	PGP_SIG_NOTATION_DATA			= 20,
Josh Boyer c2a12cd
+	PGP_SIG_PREF_HASH_ALGO			= 21,
Josh Boyer c2a12cd
+	PGP_SIG_PREF_COMPR_ALGO			= 22,
Josh Boyer c2a12cd
+	PGP_SIG_KEY_SERVER_PREFS		= 23,
Josh Boyer c2a12cd
+	PGP_SIG_PREF_KEY_SERVER			= 24,
Josh Boyer c2a12cd
+	PGP_SIG_PRIMARY_USER_ID			= 25,
Josh Boyer c2a12cd
+	PGP_SIG_POLICY_URI			= 26,
Josh Boyer c2a12cd
+	PGP_SIG_KEY_FLAGS			= 27,
Josh Boyer c2a12cd
+	PGP_SIG_SIGNERS_USER_ID			= 28,
Josh Boyer c2a12cd
+	PGP_SIG_REASON_FOR_REVOCATION		= 29,
Josh Boyer c2a12cd
+	PGP_SIG_FEATURES			= 30,
Josh Boyer c2a12cd
+	PGP_SIG_TARGET				= 31,
Josh Boyer c2a12cd
+	PGP_SIG_EMBEDDED_SIG			= 32,
Josh Boyer c2a12cd
+	PGP_SIG__LAST
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#define PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK	0x80
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Key (tag 5, 6, 7 and 14) packet
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+enum pgp_key_version {
Josh Boyer c2a12cd
+	PGP_KEY_VERSION_2			= 2,
Josh Boyer c2a12cd
+	PGP_KEY_VERSION_3			= 3,
Josh Boyer c2a12cd
+	PGP_KEY_VERSION_4			= 4,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_key_v3_packet {
Josh Boyer c2a12cd
+	enum pgp_key_version version : 8;
Josh Boyer c2a12cd
+	struct pgp_time	creation_time;
Josh Boyer c2a12cd
+	u8 expiry[2];				/* 0 or time in days till expiry */
Josh Boyer c2a12cd
+	enum pgp_pubkey_algo pubkey_algo : 8;
Josh Boyer c2a12cd
+	u8 key_material[0];
Josh Boyer c2a12cd
+} __packed;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_key_v4_packet {
Josh Boyer c2a12cd
+	enum pgp_key_version version : 8;
Josh Boyer c2a12cd
+	struct pgp_time	creation_time;
Josh Boyer c2a12cd
+	enum pgp_pubkey_algo pubkey_algo : 8;
Josh Boyer c2a12cd
+	u8 key_material[0];
Josh Boyer c2a12cd
+} __packed;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#endif /* _LINUX_PGP_H */
Josh Boyer c2a12cd
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Josh Boyer c115215
From 0b8ec95fe7220288c143a820b8d8996c356129f1 Mon Sep 17 00:00:00 2001
Josh Boyer c2a12cd
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 14:11:20 +0100
Josh Boyer c115215
Subject: [PATCH 09/28] PGPLIB: Basic packet parser
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Provide a simple parser that extracts the packets from a PGP packet blob and
Josh Boyer c2a12cd
passes the desirous ones to the given processor function:
Josh Boyer c2a12cd
Josh Boyer c2a12cd
	struct pgp_parse_context {
Josh Boyer c2a12cd
		u64 types_of_interest;
Josh Boyer c2a12cd
		int (*process_packet)(struct pgp_parse_context *context,
Josh Boyer c2a12cd
				      enum pgp_packet_tag type,
Josh Boyer c2a12cd
				      u8 headerlen,
Josh Boyer c2a12cd
				      const u8 *data,
Josh Boyer c2a12cd
				      size_t datalen);
Josh Boyer c2a12cd
	};
Josh Boyer c2a12cd
Josh Boyer c2a12cd
	int pgp_parse_packets(const u8 *data, size_t datalen,
Josh Boyer c2a12cd
			      struct pgp_parse_context *ctx);
Josh Boyer c2a12cd
Josh Boyer c2a12cd
This is configured on with CONFIG_PGP_LIBRARY.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c2a12cd
---
Josh Boyer 306dfcc
 include/linux/pgplib.h             |  47 +++++++
Josh Boyer 306dfcc
 security/keys/crypto/Kconfig       |   6 +
Josh Boyer 306dfcc
 security/keys/crypto/Makefile      |   1 +
Josh Boyer 306dfcc
 security/keys/crypto/pgp_library.c | 268 +++++++++++++++++++++++++++++++++++++
Josh Boyer 5a0e7f0
 4 files changed, 322 insertions(+)
Josh Boyer 5a0e7f0
 create mode 100644 include/linux/pgplib.h
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/pgp_library.c
Josh Boyer c2a12cd
Josh Boyer 5a0e7f0
diff --git a/include/linux/pgplib.h b/include/linux/pgplib.h
Josh Boyer 5a0e7f0
new file mode 100644
Josh Boyer 5a0e7f0
index 0000000..a045b3a
Josh Boyer 5a0e7f0
--- /dev/null
Josh Boyer 5a0e7f0
+++ b/include/linux/pgplib.h
Josh Boyer 5a0e7f0
@@ -0,0 +1,47 @@
Josh Boyer 5a0e7f0
+/* PGP library definitions (RFC 4880)
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
Josh Boyer 5a0e7f0
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * This program is free software; you can redistribute it and/or
Josh Boyer 5a0e7f0
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer 5a0e7f0
+ * as published by the Free Software Foundation; either version
Josh Boyer 5a0e7f0
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer 5a0e7f0
+ */
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#ifndef _LINUX_PGPLIB_H
Josh Boyer 5a0e7f0
+#define _LINUX_PGPLIB_H
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#if defined(CONFIG_PGP_LIBRARY) || defined(CONFIG_PGP_LIBRARY_MODULE)
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#include <linux/pgp.h>
Josh Boyer 5a0e7f0
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * PGP library packet parser
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+struct pgp_parse_context {
Josh Boyer c2a12cd
+	u64 types_of_interest;
Josh Boyer c2a12cd
+	int (*process_packet)(struct pgp_parse_context *context,
Josh Boyer c2a12cd
+			      enum pgp_packet_tag type,
Josh Boyer c2a12cd
+			      u8 headerlen,
Josh Boyer c2a12cd
+			      const u8 *data,
Josh Boyer c2a12cd
+			      size_t datalen);
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern int pgp_parse_packets(const u8 *data, size_t datalen,
Josh Boyer c2a12cd
+			     struct pgp_parse_context *ctx);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_parse_pubkey {
Josh Boyer c2a12cd
+	enum pgp_key_version version : 8;
Josh Boyer c2a12cd
+	enum pgp_pubkey_algo pubkey_algo : 8;
Josh Boyer c2a12cd
+	time_t		creation_time;
Josh Boyer c2a12cd
+	time_t		expires_at;
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
Josh Boyer c2a12cd
+				struct pgp_parse_pubkey *pk);
Josh Boyer c2a12cd
+
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#endif /* CONFIG_PGP_LIBRARY */
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#endif /* _LINUX_PGPLIB_H */
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
index 4e3777e..88ce0e2 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
@@ -22,3 +22,9 @@ config CRYPTO_KEY_PKEY_ALGO_RSA
Josh Boyer 3dd0fcf
 	select MPILIB_EXTRA
Josh Boyer c2a12cd
 	help
Josh Boyer c2a12cd
 	  This option enables support for the RSA algorithm (PKCS#1, RFC3447).
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+config PGP_LIBRARY
Josh Boyer c2a12cd
+	tristate "PGP parsing library"
Josh Boyer c2a12cd
+	help
Josh Boyer c2a12cd
+	  This option enables a library that provides a number of simple
Josh Boyer c2a12cd
+	  utility functions for parsing PGP (RFC 4880) packet-based messages.
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
index b6b1a5a..5fbe54e 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
@@ -7,3 +7,4 @@ crypto_keys-y := crypto_type.o crypto_verify.o
Josh Boyer 3dd0fcf
 
Josh Boyer c2a12cd
 obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
Josh Boyer c2a12cd
 obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
Josh Boyer c2a12cd
+obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer 5a0e7f0
index 0000000..af396d6
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/pgp_library.c
Josh Boyer 5a0e7f0
@@ -0,0 +1,268 @@
Josh Boyer c2a12cd
+/* PGP packet parser (RFC 4880)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+#define pr_fmt(fmt) "PGP: "fmt
Josh Boyer 5a0e7f0
+#include <linux/pgplib.h>
Josh Boyer c2a12cd
+#include <linux/errno.h>
Josh Boyer c2a12cd
+#include <linux/kernel.h>
Josh Boyer c2a12cd
+#include <linux/module.h>
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+MODULE_LICENSE("GPL");
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+const char *const pgp_hash_algorithms[PGP_HASH__LAST] = {
Josh Boyer c2a12cd
+	[PGP_HASH_MD5]			= "md5",
Josh Boyer c2a12cd
+	[PGP_HASH_SHA1]			= "sha1",
Josh Boyer c2a12cd
+	[PGP_HASH_RIPE_MD_160]		= "rmd160",
Josh Boyer c2a12cd
+	[PGP_HASH_SHA256]		= "sha256",
Josh Boyer c2a12cd
+	[PGP_HASH_SHA384]		= "sha384",
Josh Boyer c2a12cd
+	[PGP_HASH_SHA512]		= "sha512",
Josh Boyer c2a12cd
+	[PGP_HASH_SHA224]		= "sha224",
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(pgp_hash_algorithms);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * pgp_parse_packet_header - Parse a PGP packet header
Josh Boyer c2a12cd
+ * @_data: Start of the PGP packet (updated to PGP packet data)
Josh Boyer c2a12cd
+ * @_datalen: Amount of data remaining in buffer (decreased)
Josh Boyer c2a12cd
+ * @_type: Where the packet type will be returned
Josh Boyer c2a12cd
+ * @_headerlen: Where the header length will be returned
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Parse a set of PGP packet header [RFC 4880: 4.2].
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Returns packet data size on success; non-zero on error.  If successful,
Josh Boyer c2a12cd
+ * *_data and *_datalen will have been updated and *_headerlen will be set to
Josh Boyer c2a12cd
+ * hold the length of the packet header.
Josh Boyer c2a12cd
+ */
Josh Boyer 5a0e7f0
+static ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen,
Josh Boyer 5a0e7f0
+				       enum pgp_packet_tag *_type,
Josh Boyer 5a0e7f0
+				       u8 *_headerlen)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	enum pgp_packet_tag type;
Josh Boyer c2a12cd
+	const u8 *data = *_data;
Josh Boyer c2a12cd
+	size_t size, datalen = *_datalen;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("-->pgp_parse_packet_header(,%zu,,)", datalen);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (datalen < 2)
Josh Boyer c2a12cd
+		goto short_packet;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("pkthdr %02x, %02x\n", data[0], data[1]);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	type = *data++;
Josh Boyer c2a12cd
+	datalen--;
Josh Boyer c2a12cd
+	if (!(type & 0x80)) {
Josh Boyer c2a12cd
+		pr_debug("Packet type does not have MSB set\n");
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+	type &= ~0x80;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (type & 0x40) {
Josh Boyer c2a12cd
+		/* New packet length format */
Josh Boyer c2a12cd
+		type &= ~0x40;
Josh Boyer c2a12cd
+		pr_devel("new format: t=%u\n", type);
Josh Boyer c2a12cd
+		switch (data[0]) {
Josh Boyer c2a12cd
+		case 0x00 ... 0xbf:
Josh Boyer c2a12cd
+			/* One-byte length */
Josh Boyer c2a12cd
+			size = data[0];
Josh Boyer c2a12cd
+			data++;
Josh Boyer c2a12cd
+			datalen--;
Josh Boyer c2a12cd
+			*_headerlen = 2;
Josh Boyer c2a12cd
+			break;
Josh Boyer c2a12cd
+		case 0xc0 ... 0xdf:
Josh Boyer c2a12cd
+			/* Two-byte length */
Josh Boyer c2a12cd
+			if (datalen < 2)
Josh Boyer c2a12cd
+				goto short_packet;
Josh Boyer c2a12cd
+			size = (data[0] - 192) * 256;
Josh Boyer c2a12cd
+			size += data[1] + 192;
Josh Boyer c2a12cd
+			data += 2;
Josh Boyer c2a12cd
+			datalen -= 2;
Josh Boyer c2a12cd
+			*_headerlen = 3;
Josh Boyer c2a12cd
+			break;
Josh Boyer c2a12cd
+		case 0xff:
Josh Boyer 5a0e7f0
+			/* Five-byte length */
Josh Boyer 5a0e7f0
+			if (datalen < 5)
Josh Boyer 5a0e7f0
+				goto short_packet;
Josh Boyer 5a0e7f0
+			size =  data[1] << 24;
Josh Boyer 5a0e7f0
+			size |= data[2] << 16;
Josh Boyer 5a0e7f0
+			size |= data[3] << 8;
Josh Boyer 5a0e7f0
+			size |= data[4];
Josh Boyer 5a0e7f0
+			data += 5;
Josh Boyer 5a0e7f0
+			datalen -= 5;
Josh Boyer 5a0e7f0
+			*_headerlen = 6;
Josh Boyer 5a0e7f0
+			break;
Josh Boyer c2a12cd
+		default:
Josh Boyer 5a0e7f0
+			pr_debug("Partial body length packet not supported\n");
Josh Boyer c2a12cd
+			return -EBADMSG;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+	} else {
Josh Boyer c2a12cd
+		/* Old packet length format */
Josh Boyer c2a12cd
+		u8 length_type = type & 0x03;
Josh Boyer c2a12cd
+		type >>= 2;
Josh Boyer c2a12cd
+		pr_devel("old format: t=%u lt=%u\n", type, length_type);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		switch (length_type) {
Josh Boyer c2a12cd
+		case 0:
Josh Boyer c2a12cd
+			/* One-byte length */
Josh Boyer c2a12cd
+			size = data[0];
Josh Boyer c2a12cd
+			data++;
Josh Boyer c2a12cd
+			datalen--;
Josh Boyer c2a12cd
+			*_headerlen = 2;
Josh Boyer c2a12cd
+			break;
Josh Boyer c2a12cd
+		case 1:
Josh Boyer c2a12cd
+			/* Two-byte length */
Josh Boyer c2a12cd
+			if (datalen < 2)
Josh Boyer c2a12cd
+				goto short_packet;
Josh Boyer c2a12cd
+			size  = data[0] << 8;
Josh Boyer c2a12cd
+			size |= data[1];
Josh Boyer c2a12cd
+			data += 2;
Josh Boyer c2a12cd
+			datalen -= 2;
Josh Boyer c2a12cd
+			*_headerlen = 3;
Josh Boyer c2a12cd
+			break;
Josh Boyer c2a12cd
+		case 2:
Josh Boyer c2a12cd
+			/* Four-byte length */
Josh Boyer c2a12cd
+			if (datalen < 4)
Josh Boyer c2a12cd
+				goto short_packet;
Josh Boyer c2a12cd
+			size  = data[0] << 24;
Josh Boyer c2a12cd
+			size |= data[1] << 16;
Josh Boyer c2a12cd
+			size |= data[2] << 8;
Josh Boyer c2a12cd
+			size |= data[3];
Josh Boyer c2a12cd
+			data += 4;
Josh Boyer c2a12cd
+			datalen -= 4;
Josh Boyer c2a12cd
+			*_headerlen = 5;
Josh Boyer c2a12cd
+			break;
Josh Boyer c2a12cd
+		default:
Josh Boyer c2a12cd
+			pr_debug("Indefinite length packet not supported\n");
Josh Boyer c2a12cd
+			return -EBADMSG;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("datalen=%zu size=%zu", datalen, size);
Josh Boyer c2a12cd
+	if (datalen < size)
Josh Boyer c2a12cd
+		goto short_packet;
Josh Boyer 5a0e7f0
+	if ((int)size < 0)
Josh Boyer 5a0e7f0
+		goto too_big;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	*_data = data;
Josh Boyer c2a12cd
+	*_datalen = datalen;
Josh Boyer c2a12cd
+	*_type = type;
Josh Boyer c2a12cd
+	pr_devel("Found packet type=%u size=%zd\n", type, size);
Josh Boyer c2a12cd
+	return size;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+short_packet:
Josh Boyer c2a12cd
+	pr_debug("Attempt to parse short packet\n");
Josh Boyer c2a12cd
+	return -EBADMSG;
Josh Boyer 5a0e7f0
+too_big:
Josh Boyer 5a0e7f0
+	pr_debug("Signature subpacket size >2G\n");
Josh Boyer 5a0e7f0
+	return -EMSGSIZE;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * pgp_parse_packets - Parse a set of PGP packets
Josh Boyer c2a12cd
+ * @_data: Data to be parsed (updated)
Josh Boyer c2a12cd
+ * @_datalen: Amount of data (updated)
Josh Boyer c2a12cd
+ * @ctx: Parsing context
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Parse a set of PGP packets [RFC 4880: 4].
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+int pgp_parse_packets(const u8 *data, size_t datalen,
Josh Boyer c2a12cd
+		      struct pgp_parse_context *ctx)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	enum pgp_packet_tag type;
Josh Boyer c2a12cd
+	ssize_t pktlen;
Josh Boyer c2a12cd
+	u8 headerlen;
Josh Boyer c2a12cd
+	int ret;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	while (datalen > 2) {
Josh Boyer c2a12cd
+		pktlen = pgp_parse_packet_header(&data, &datalen, &type,
Josh Boyer c2a12cd
+						 &headerlen);
Josh Boyer c2a12cd
+		if (pktlen < 0)
Josh Boyer c2a12cd
+			return pktlen;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		if ((ctx->types_of_interest >> type) & 1) {
Josh Boyer c2a12cd
+			ret = ctx->process_packet(ctx, type, headerlen,
Josh Boyer c2a12cd
+						  data, pktlen);
Josh Boyer c2a12cd
+			if (ret < 0)
Josh Boyer c2a12cd
+				return ret;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+		data += pktlen;
Josh Boyer c2a12cd
+		datalen -= pktlen;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (datalen != 0) {
Josh Boyer c2a12cd
+		pr_debug("Excess octets in packet stream\n");
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	return 0;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(pgp_parse_packets);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * pgp_parse_public_key - Parse the common part of a PGP pubkey packet
Josh Boyer c2a12cd
+ * @_data: Content of packet (updated)
Josh Boyer c2a12cd
+ * @_datalen: Length of packet remaining (updated)
Josh Boyer c2a12cd
+ * @pk: Public key data
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Parse the common data struct for a PGP pubkey packet [RFC 4880: 5.5.2].
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
Josh Boyer c2a12cd
+			 struct pgp_parse_pubkey *pk)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	const u8 *data = *_data;
Josh Boyer c2a12cd
+	size_t datalen = *_datalen;
Josh Boyer c2a12cd
+	__be32 tmp;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (datalen < 12) {
Josh Boyer c2a12cd
+		pr_debug("Public key packet too short\n");
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pk->version = *data++;
Josh Boyer c2a12cd
+	switch (pk->version) {
Josh Boyer c2a12cd
+	case PGP_KEY_VERSION_2:
Josh Boyer c2a12cd
+	case PGP_KEY_VERSION_3:
Josh Boyer c2a12cd
+	case PGP_KEY_VERSION_4:
Josh Boyer c2a12cd
+		break;
Josh Boyer c2a12cd
+	default:
Josh Boyer c2a12cd
+		pr_debug("Public key packet with unhandled version %d\n",
Josh Boyer c2a12cd
+			   pk->version);
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	tmp  = *data++ << 24;
Josh Boyer c2a12cd
+	tmp |= *data++ << 16;
Josh Boyer c2a12cd
+	tmp |= *data++ << 8;
Josh Boyer c2a12cd
+	tmp |= *data++;
Josh Boyer c2a12cd
+	pk->creation_time = tmp;
Josh Boyer c2a12cd
+	if (pk->version == PGP_KEY_VERSION_4) {
Josh Boyer c2a12cd
+		pk->expires_at = 0; /* Have to get it from the selfsignature */
Josh Boyer c2a12cd
+	} else {
Josh Boyer c2a12cd
+		unsigned short ndays;
Josh Boyer c2a12cd
+		ndays  = *data++ << 8;
Josh Boyer c2a12cd
+		ndays |= *data++;
Josh Boyer c2a12cd
+		if (ndays)
Josh Boyer c2a12cd
+			pk->expires_at = pk->creation_time + ndays * 86400UL;
Josh Boyer c2a12cd
+		else
Josh Boyer c2a12cd
+			pk->expires_at = 0;
Josh Boyer c2a12cd
+		datalen -= 2;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pk->pubkey_algo = *data++;
Josh Boyer c2a12cd
+	datalen -= 6;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("%x,%x,%lx,%lx",
Josh Boyer c2a12cd
+		 pk->version, pk->pubkey_algo, pk->creation_time,
Josh Boyer c2a12cd
+		 pk->expires_at);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	*_data = data;
Josh Boyer c2a12cd
+	*_datalen = datalen;
Josh Boyer c2a12cd
+	return 0;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(pgp_parse_public_key);
Josh Boyer c2a12cd
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Josh Boyer c115215
From a3673ac73f4634bcdd97d642b3bdd87998eb2100 Mon Sep 17 00:00:00 2001
Josh Boyer c2a12cd
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 14:11:20 +0100
Josh Boyer c115215
Subject: [PATCH 10/28] PGPLIB: Signature parser
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Provide some PGP signature parsing helpers:
Josh Boyer c2a12cd
Josh Boyer c2a12cd
 (1) A function to parse V4 signature subpackets and pass the desired ones to
Josh Boyer c2a12cd
     a processor function:
Josh Boyer c2a12cd
Josh Boyer c2a12cd
	int pgp_parse_sig_subpkts(const u8 *data, size_t datalen,
Josh Boyer c2a12cd
				  struct pgp_parse_sig_context *ctx);
Josh Boyer c2a12cd
Josh Boyer c2a12cd
 (2) A function to parse out basic signature parameters from any PGP signature
Josh Boyer c2a12cd
     such that the algorithms and public key can be selected:
Josh Boyer c2a12cd
Josh Boyer c2a12cd
	int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
Josh Boyer c2a12cd
				 struct pgp_sig_parameters *p);
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c2a12cd
---
Josh Boyer 306dfcc
 include/linux/pgplib.h             |  25 ++++
Josh Boyer 306dfcc
 security/keys/crypto/pgp_library.c | 280 +++++++++++++++++++++++++++++++++++++
Josh Boyer 5a0e7f0
 2 files changed, 305 insertions(+)
Josh Boyer 5a0e7f0
Josh Boyer 5a0e7f0
diff --git a/include/linux/pgplib.h b/include/linux/pgplib.h
Josh Boyer 5a0e7f0
index a045b3a..34594a9 100644
Josh Boyer 5a0e7f0
--- a/include/linux/pgplib.h
Josh Boyer 5a0e7f0
+++ b/include/linux/pgplib.h
Josh Boyer 5a0e7f0
@@ -41,6 +41,31 @@ struct pgp_parse_pubkey {
Josh Boyer c2a12cd
 extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
Josh Boyer c2a12cd
 				struct pgp_parse_pubkey *pk);
Josh Boyer c2a12cd
 
Josh Boyer c2a12cd
+struct pgp_parse_sig_context {
Josh Boyer c2a12cd
+	unsigned long types_of_interest[128 / BITS_PER_LONG];
Josh Boyer c2a12cd
+	int (*process_packet)(struct pgp_parse_sig_context *context,
Josh Boyer c2a12cd
+			      enum pgp_sig_subpkt_type type,
Josh Boyer c2a12cd
+			      const u8 *data,
Josh Boyer c2a12cd
+			      size_t datalen);
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern int pgp_parse_sig_packets(const u8 *data, size_t datalen,
Josh Boyer c2a12cd
+				 struct pgp_parse_sig_context *ctx);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_sig_parameters {
Josh Boyer 5a0e7f0
+	enum pgp_signature_version version : 8;
Josh Boyer c2a12cd
+	enum pgp_signature_type signature_type : 8;
Josh Boyer 5a0e7f0
+	enum pgp_pubkey_algo pubkey_algo : 8;
Josh Boyer 5a0e7f0
+	enum pgp_hash_algo hash_algo : 8;
Josh Boyer c2a12cd
+	union {
Josh Boyer c2a12cd
+		struct pgp_key_ID issuer;
Josh Boyer c2a12cd
+		__be32 issuer32[2];
Josh Boyer c2a12cd
+	};
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+extern int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
Josh Boyer c2a12cd
+				struct pgp_sig_parameters *p);
Josh Boyer c2a12cd
+
Josh Boyer 5a0e7f0
 
Josh Boyer 5a0e7f0
 #endif /* CONFIG_PGP_LIBRARY */
Josh Boyer 5a0e7f0
 
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c
Josh Boyer 5a0e7f0
index af396d6..c9218df 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/pgp_library.c
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/pgp_library.c
Josh Boyer 5a0e7f0
@@ -266,3 +266,283 @@ int pgp_parse_public_key(const u8 **_data, size_t *_datalen,
Josh Boyer c2a12cd
 	return 0;
Josh Boyer c2a12cd
 }
Josh Boyer c2a12cd
 EXPORT_SYMBOL_GPL(pgp_parse_public_key);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * pgp_parse_sig_subpkt_header - Parse a PGP V4 signature subpacket header
Josh Boyer c2a12cd
+ * @_data: Start of the subpacket (updated to subpacket data)
Josh Boyer c2a12cd
+ * @_datalen: Amount of data remaining in buffer (decreased)
Josh Boyer c2a12cd
+ * @_type: Where the subpacket type will be returned
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Parse a PGP V4 signature subpacket header [RFC 4880: 5.2.3.1].
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Returns packet data size on success; non-zero on error.  If successful,
Josh Boyer c2a12cd
+ * *_data and *_datalen will have been updated and *_headerlen will be set to
Josh Boyer c2a12cd
+ * hold the length of the packet header.
Josh Boyer c2a12cd
+ */
Josh Boyer 5a0e7f0
+static ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen,
Josh Boyer 5a0e7f0
+					   enum pgp_sig_subpkt_type *_type)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	enum pgp_sig_subpkt_type type;
Josh Boyer c2a12cd
+	const u8 *data = *_data;
Josh Boyer c2a12cd
+	size_t size, datalen = *_datalen;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("-->pgp_parse_sig_subpkt_header(,%zu,,)", datalen);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (datalen < 2)
Josh Boyer c2a12cd
+		goto short_subpacket;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("subpkt hdr %02x, %02x\n", data[0], data[1]);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	switch (data[0]) {
Josh Boyer c2a12cd
+	case 0x00 ... 0xbf:
Josh Boyer c2a12cd
+		/* One-byte length */
Josh Boyer c2a12cd
+		size = data[0];
Josh Boyer c2a12cd
+		data++;
Josh Boyer c2a12cd
+		datalen--;
Josh Boyer c2a12cd
+		break;
Josh Boyer c2a12cd
+	case 0xc0 ... 0xfe:
Josh Boyer c2a12cd
+		/* Two-byte length */
Josh Boyer c2a12cd
+		if (datalen < 3)
Josh Boyer c2a12cd
+			goto short_subpacket;
Josh Boyer c2a12cd
+		size = (data[0] - 192) * 256;
Josh Boyer c2a12cd
+		size += data[1] + 192;
Josh Boyer c2a12cd
+		data += 2;
Josh Boyer c2a12cd
+		datalen -= 2;
Josh Boyer c2a12cd
+		break;
Josh Boyer c2a12cd
+	case 0xff:
Josh Boyer c2a12cd
+		if (datalen < 6)
Josh Boyer c2a12cd
+			goto short_subpacket;
Josh Boyer c2a12cd
+		size  = data[1] << 24;
Josh Boyer c2a12cd
+		size |= data[2] << 16;
Josh Boyer c2a12cd
+		size |= data[3] << 8;
Josh Boyer c2a12cd
+		size |= data[4];
Josh Boyer c2a12cd
+		data += 5;
Josh Boyer c2a12cd
+		datalen -= 5;
Josh Boyer c2a12cd
+		break;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	/* The type octet is included in the size */
Josh Boyer 5a0e7f0
+	pr_devel("datalen=%zu size=%zu", datalen, size);
Josh Boyer 5a0e7f0
+	if (datalen < size)
Josh Boyer 5a0e7f0
+		goto short_subpacket;
Josh Boyer 5a0e7f0
+	if (size == 0)
Josh Boyer 5a0e7f0
+		goto very_short_subpacket;
Josh Boyer 5a0e7f0
+	if ((int)size < 0)
Josh Boyer 5a0e7f0
+		goto too_big;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	type = *data++ & ~PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK;
Josh Boyer c2a12cd
+	datalen--;
Josh Boyer c2a12cd
+	size--;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	*_data = data;
Josh Boyer c2a12cd
+	*_datalen = datalen;
Josh Boyer c2a12cd
+	*_type = type;
Josh Boyer c2a12cd
+	pr_devel("Found subpkt type=%u size=%zd\n", type, size);
Josh Boyer c2a12cd
+	return size;
Josh Boyer c2a12cd
+
Josh Boyer 5a0e7f0
+very_short_subpacket:
Josh Boyer 5a0e7f0
+	pr_debug("Signature subpacket size can't be zero\n");
Josh Boyer 5a0e7f0
+	return -EBADMSG;
Josh Boyer c2a12cd
+short_subpacket:
Josh Boyer c2a12cd
+	pr_debug("Attempt to parse short signature subpacket\n");
Josh Boyer c2a12cd
+	return -EBADMSG;
Josh Boyer 5a0e7f0
+too_big:
Josh Boyer 5a0e7f0
+	pr_debug("Signature subpacket size >2G\n");
Josh Boyer 5a0e7f0
+	return -EMSGSIZE;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * pgp_parse_sig_subpkts - Parse a set of PGP V4 signatute subpackets
Josh Boyer c2a12cd
+ * @_data: Data to be parsed (updated)
Josh Boyer c2a12cd
+ * @_datalen: Amount of data (updated)
Josh Boyer c2a12cd
+ * @ctx: Parsing context
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Parse a set of PGP signature subpackets [RFC 4880: 5.2.3].
Josh Boyer c2a12cd
+ */
Josh Boyer 5a0e7f0
+static int pgp_parse_sig_subpkts(const u8 *data, size_t datalen,
Josh Boyer 5a0e7f0
+				 struct pgp_parse_sig_context *ctx)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	enum pgp_sig_subpkt_type type;
Josh Boyer c2a12cd
+	ssize_t pktlen;
Josh Boyer c2a12cd
+	int ret;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("-->pgp_parse_sig_subpkts(,%zu,,)", datalen);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	while (datalen > 2) {
Josh Boyer c2a12cd
+		pktlen = pgp_parse_sig_subpkt_header(&data, &datalen, &type);
Josh Boyer c2a12cd
+		if (pktlen < 0)
Josh Boyer c2a12cd
+			return pktlen;
Josh Boyer c2a12cd
+		if (test_bit(type, ctx->types_of_interest)) {
Josh Boyer c2a12cd
+			ret = ctx->process_packet(ctx, type, data, pktlen);
Josh Boyer c2a12cd
+			if (ret < 0)
Josh Boyer c2a12cd
+				return ret;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+		data += pktlen;
Josh Boyer c2a12cd
+		datalen -= pktlen;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (datalen != 0) {
Josh Boyer c2a12cd
+		pr_debug("Excess octets in signature subpacket stream\n");
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	return 0;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_parse_sig_params_ctx {
Josh Boyer c2a12cd
+	struct pgp_parse_sig_context base;
Josh Boyer c2a12cd
+	struct pgp_sig_parameters *params;
Josh Boyer c2a12cd
+	bool got_the_issuer;
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Process a V4 signature subpacket.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int pgp_process_sig_params_subpkt(struct pgp_parse_sig_context *context,
Josh Boyer c2a12cd
+					 enum pgp_sig_subpkt_type type,
Josh Boyer c2a12cd
+					 const u8 *data,
Josh Boyer c2a12cd
+					 size_t datalen)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct pgp_parse_sig_params_ctx *ctx =
Josh Boyer c2a12cd
+		container_of(context, struct pgp_parse_sig_params_ctx, base);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (ctx->got_the_issuer) {
Josh Boyer c2a12cd
+		pr_debug("V4 signature packet has multiple issuers\n");
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (datalen != 8) {
Josh Boyer c2a12cd
+		pr_debug("V4 signature issuer subpkt not 8 long (%zu)\n",
Josh Boyer c2a12cd
+			   datalen);
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	memcpy(&ctx->params->issuer, data, 8);
Josh Boyer c2a12cd
+	ctx->got_the_issuer = true;
Josh Boyer c2a12cd
+	return 0;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/**
Josh Boyer c2a12cd
+ * pgp_parse_sig_params - Parse basic parameters from a PGP signature packet
Josh Boyer c2a12cd
+ * @_data: Content of packet (updated)
Josh Boyer c2a12cd
+ * @_datalen: Length of packet remaining (updated)
Josh Boyer c2a12cd
+ * @p: The basic parameters
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Parse the basic parameters from a PGP signature packet [RFC 4880: 5.2] that
Josh Boyer c2a12cd
+ * are needed to start off a signature verification operation.  The only ones
Josh Boyer c2a12cd
+ * actually necessary are the signature type (which affects how the data is
Josh Boyer 5a0e7f0
+ * transformed) and the hash algorithm.
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * We also extract the public key algorithm and the issuer's key ID as we'll
Josh Boyer c2a12cd
+ * need those to determine if we actually have the public key available.  If
Josh Boyer c2a12cd
+ * not, then we can't verify the signature anyway.
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Returns 0 if successful or a negative error code.  *_data and *_datalen are
Josh Boyer c2a12cd
+ * updated to point to the 16-bit subset of the hash value and the set of MPIs.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+int pgp_parse_sig_params(const u8 **_data, size_t *_datalen,
Josh Boyer c2a12cd
+			 struct pgp_sig_parameters *p)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	const u8 *data = *_data;
Josh Boyer c2a12cd
+	size_t datalen = *_datalen;
Josh Boyer c2a12cd
+	int ret;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	pr_devel("-->pgp_parse_sig_params(,%zu,,)", datalen);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (datalen < 1)
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer 5a0e7f0
+	p->version = *data;
Josh Boyer c2a12cd
+
Josh Boyer 5a0e7f0
+	if (p->version == PGP_SIG_VERSION_3) {
Josh Boyer c2a12cd
+		const struct pgp_signature_v3_packet *v3 = (const void *)data;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		if (datalen < sizeof(*v3)) {
Josh Boyer c2a12cd
+			pr_debug("Short V3 signature packet\n");
Josh Boyer c2a12cd
+			return -EBADMSG;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+		datalen -= sizeof(*v3);
Josh Boyer c2a12cd
+		data += sizeof(*v3);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		/* V3 has everything we need in the header */
Josh Boyer c2a12cd
+		p->signature_type = v3->hashed.signature_type;
Josh Boyer c2a12cd
+		p->issuer = v3->issuer;
Josh Boyer c2a12cd
+		p->pubkey_algo = v3->pubkey_algo;
Josh Boyer c2a12cd
+		p->hash_algo = v3->hash_algo;
Josh Boyer c2a12cd
+
Josh Boyer 5a0e7f0
+	} else if (p->version == PGP_SIG_VERSION_4) {
Josh Boyer c2a12cd
+		const struct pgp_signature_v4_packet *v4 = (const void *)data;
Josh Boyer c2a12cd
+		struct pgp_parse_sig_params_ctx ctx = {
Josh Boyer c2a12cd
+			.base.process_packet = pgp_process_sig_params_subpkt,
Josh Boyer c2a12cd
+			.params = p,
Josh Boyer c2a12cd
+			.got_the_issuer = false,
Josh Boyer c2a12cd
+		};
Josh Boyer c2a12cd
+		size_t subdatalen;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		if (datalen < sizeof(*v4) + 2 + 2 + 2) {
Josh Boyer c2a12cd
+			pr_debug("Short V4 signature packet\n");
Josh Boyer c2a12cd
+			return -EBADMSG;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+		datalen -= sizeof(*v4);
Josh Boyer c2a12cd
+		data += sizeof(*v4);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		/* V4 has most things in the header... */
Josh Boyer c2a12cd
+		p->signature_type = v4->signature_type;
Josh Boyer c2a12cd
+		p->pubkey_algo = v4->pubkey_algo;
Josh Boyer c2a12cd
+		p->hash_algo = v4->hash_algo;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		/* ... but we have to get the key ID from the subpackets, of
Josh Boyer c2a12cd
+		 * which there are two sets. */
Josh Boyer c2a12cd
+		__set_bit(PGP_SIG_ISSUER, ctx.base.types_of_interest);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		subdatalen  = *data++ << 8;
Josh Boyer c2a12cd
+		subdatalen |= *data++;
Josh Boyer c2a12cd
+		datalen -= 2;
Josh Boyer c2a12cd
+		if (subdatalen) {
Josh Boyer c2a12cd
+			/* Hashed subpackets */
Josh Boyer c2a12cd
+			pr_devel("hashed data: %zu (after %zu)\n",
Josh Boyer c2a12cd
+				 subdatalen, sizeof(*v4));
Josh Boyer c2a12cd
+			if (subdatalen > datalen + 2 + 2) {
Josh Boyer c2a12cd
+				pr_debug("Short V4 signature packet [hdata]\n");
Josh Boyer c2a12cd
+				return -EBADMSG;
Josh Boyer c2a12cd
+			}
Josh Boyer c2a12cd
+			ret = pgp_parse_sig_subpkts(data, subdatalen,
Josh Boyer c2a12cd
+						    &ctx.base);
Josh Boyer c2a12cd
+			if (ret < 0)
Josh Boyer c2a12cd
+				return ret;
Josh Boyer c2a12cd
+			data += subdatalen;
Josh Boyer 5a0e7f0
+			datalen -= subdatalen;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		subdatalen  = *data++ << 8;
Josh Boyer c2a12cd
+		subdatalen |= *data++;
Josh Boyer c2a12cd
+		datalen -= 2;
Josh Boyer c2a12cd
+		if (subdatalen) {
Josh Boyer c2a12cd
+			/* Unhashed subpackets */
Josh Boyer c2a12cd
+			pr_devel("unhashed data: %zu\n", subdatalen);
Josh Boyer c2a12cd
+			if (subdatalen > datalen + 2) {
Josh Boyer c2a12cd
+				pr_debug("Short V4 signature packet [udata]\n");
Josh Boyer c2a12cd
+				return -EBADMSG;
Josh Boyer c2a12cd
+			}
Josh Boyer c2a12cd
+			ret = pgp_parse_sig_subpkts(data, subdatalen,
Josh Boyer c2a12cd
+						    &ctx.base);
Josh Boyer c2a12cd
+			if (ret < 0)
Josh Boyer c2a12cd
+				return ret;
Josh Boyer c2a12cd
+			data += subdatalen;
Josh Boyer 5a0e7f0
+			datalen -= subdatalen;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+		if (!ctx.got_the_issuer) {
Josh Boyer c2a12cd
+			pr_debug("V4 signature packet lacks issuer\n");
Josh Boyer c2a12cd
+			return -EBADMSG;
Josh Boyer c2a12cd
+		}
Josh Boyer c2a12cd
+	} else {
Josh Boyer c2a12cd
+		pr_debug("Signature packet with unhandled version %d\n",
Josh Boyer 5a0e7f0
+			 p->version);
Josh Boyer c2a12cd
+		return -EBADMSG;
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	*_data = data;
Josh Boyer c2a12cd
+	*_datalen = datalen;
Josh Boyer c2a12cd
+	return 0;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+EXPORT_SYMBOL_GPL(pgp_parse_sig_params);
Josh Boyer c2a12cd
-- 
Josh Boyer 306dfcc
1.7.11.2
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Josh Boyer c115215
From dd59f49ce7179b145f55bdca3b43f4761ae0769d Mon Sep 17 00:00:00 2001
Josh Boyer c2a12cd
From: David Howells <dhowells@redhat.com>
Josh Boyer 306dfcc
Date: Tue, 24 Jul 2012 14:11:21 +0100
Josh Boyer c115215
Subject: [PATCH 11/28] KEYS: PGP data parser
Josh Boyer c2a12cd
Josh Boyer c2a12cd
Implement a PGP data parser for the crypto key type to use when instantiating a
Josh Boyer c2a12cd
key.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
This parser attempts to parse the instantiation data as a PGP packet sequence
Josh Boyer c2a12cd
(RFC 4880) and if it parses okay, attempts to extract a public-key algorithm
Josh Boyer c2a12cd
key or subkey from it.
Josh Boyer c2a12cd
Josh Boyer c2a12cd
If it finds such a key, it will set up a public_key subtype payload with
Josh Boyer c2a12cd
appropriate handler routines (DSA or RSA) and attach it to the key.
Josh Boyer c2a12cd
Josh Boyer 5a0e7f0
Thanks to Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> for pointing out
Josh Boyer 5a0e7f0
some errors.
Josh Boyer 5a0e7f0
Josh Boyer c2a12cd
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer c2a12cd
---
Josh Boyer 306dfcc
 security/keys/crypto/Kconfig          |  12 ++
Josh Boyer 306dfcc
 security/keys/crypto/Makefile         |   4 +
Josh Boyer 306dfcc
 security/keys/crypto/pgp_parser.h     |  23 +++
Josh Boyer 306dfcc
 security/keys/crypto/pgp_public_key.c | 348 ++++++++++++++++++++++++++++++++++
Josh Boyer 5a0e7f0
 4 files changed, 387 insertions(+)
Josh Boyer 3dd0fcf
 create mode 100644 security/keys/crypto/pgp_parser.h
Josh Boyer 5a0e7f0
 create mode 100644 security/keys/crypto/pgp_public_key.c
Josh Boyer 3dd0fcf
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
index 88ce0e2..1c2ae55 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Kconfig
Josh Boyer 3dd0fcf
@@ -28,3 +28,15 @@ config PGP_LIBRARY
Josh Boyer c2a12cd
 	help
Josh Boyer c2a12cd
 	  This option enables a library that provides a number of simple
Josh Boyer c2a12cd
 	  utility functions for parsing PGP (RFC 4880) packet-based messages.
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+config CRYPTO_KEY_PGP_PARSER
Josh Boyer c2a12cd
+	tristate "PGP key blob parser"
Josh Boyer c2a12cd
+	depends on CRYPTO_KEY_TYPE
Josh Boyer c2a12cd
+	select CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
Josh Boyer c2a12cd
+	select PGP_LIBRARY
Josh Boyer c2a12cd
+	select MD5 # V3 fingerprint generation
Josh Boyer c2a12cd
+	select SHA1 # V4 fingerprint generation
Josh Boyer c2a12cd
+	help
Josh Boyer c2a12cd
+	  This option provides support for parsing PGP (RFC 4880) format blobs
Josh Boyer c2a12cd
+	  for key data and provides the ability to instantiate a crypto key
Josh Boyer c2a12cd
+	  from a public key packet found inside the blob.
Josh Boyer 3dd0fcf
diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
Josh Boyer 5a0e7f0
index 5fbe54e..35733fc 100644
Josh Boyer 3dd0fcf
--- a/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
+++ b/security/keys/crypto/Makefile
Josh Boyer 3dd0fcf
@@ -8,3 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.o
Josh Boyer c2a12cd
 obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
Josh Boyer c2a12cd
 obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
Josh Boyer c2a12cd
 obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
Josh Boyer c2a12cd
+
Josh Boyer 5a0e7f0
+obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o
Josh Boyer 5a0e7f0
+pgp_key_parser-y := \
Josh Boyer 5a0e7f0
+	pgp_public_key.o
Josh Boyer 5a0e7f0
diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h
Josh Boyer 5a0e7f0
new file mode 100644
Josh Boyer 5a0e7f0
index 0000000..1cda231
Josh Boyer 5a0e7f0
--- /dev/null
Josh Boyer 5a0e7f0
+++ b/security/keys/crypto/pgp_parser.h
Josh Boyer 5a0e7f0
@@ -0,0 +1,23 @@
Josh Boyer 5a0e7f0
+/* PGP crypto data parser internal definitions
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer 5a0e7f0
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer 5a0e7f0
+ *
Josh Boyer 5a0e7f0
+ * This program is free software; you can redistribute it and/or
Josh Boyer 5a0e7f0
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer 5a0e7f0
+ * as published by the Free Software Foundation; either version
Josh Boyer 5a0e7f0
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer 5a0e7f0
+ */
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#include <linux/pgp.h>
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+#define kenter(FMT, ...) \
Josh Boyer 5a0e7f0
+	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
Josh Boyer 5a0e7f0
+#define kleave(FMT, ...) \
Josh Boyer 5a0e7f0
+	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
Josh Boyer 5a0e7f0
+
Josh Boyer 5a0e7f0
+/*
Josh Boyer 5a0e7f0
+ * pgp_key_parser.c
Josh Boyer 5a0e7f0
+ */
Josh Boyer 5a0e7f0
+extern const
Josh Boyer 5a0e7f0
+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST];
Josh Boyer 5a0e7f0
diff --git a/security/keys/crypto/pgp_public_key.c b/security/keys/crypto/pgp_public_key.c
Josh Boyer c2a12cd
new file mode 100644
Josh Boyer 5a0e7f0
index 0000000..8a8b7c0
Josh Boyer c2a12cd
--- /dev/null
Josh Boyer 5a0e7f0
+++ b/security/keys/crypto/pgp_public_key.c
Josh Boyer 5a0e7f0
@@ -0,0 +1,348 @@
Josh Boyer 5a0e7f0
+/* Instantiate a public key crypto key from PGP format data [RFC 4880]
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
Josh Boyer c2a12cd
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer c2a12cd
+ *
Josh Boyer c2a12cd
+ * This program is free software; you can redistribute it and/or
Josh Boyer c2a12cd
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer c2a12cd
+ * as published by the Free Software Foundation; either version
Josh Boyer c2a12cd
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+#define pr_fmt(fmt) "PGP: "fmt
Josh Boyer c2a12cd
+#include <keys/crypto-subtype.h>
Josh Boyer c2a12cd
+#include <linux/module.h>
Josh Boyer c2a12cd
+#include <linux/kernel.h>
Josh Boyer c2a12cd
+#include <linux/slab.h>
Josh Boyer c2a12cd
+#include <linux/mpi.h>
Josh Boyer 5a0e7f0
+#include <linux/pgplib.h>
Josh Boyer c2a12cd
+#include <crypto/hash.h>
Josh Boyer c2a12cd
+#include "public_key.h"
Josh Boyer c2a12cd
+#include "pgp_parser.h"
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+MODULE_LICENSE("GPL");
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+const
Josh Boyer c2a12cd
+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST] = {
Josh Boyer c2a12cd
+#if defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) || \
Josh Boyer c2a12cd
+	defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA_MODULE)
Josh Boyer c2a12cd
+	[PGP_PUBKEY_RSA_ENC_OR_SIG]	= &RSA_public_key_algorithm,
Josh Boyer c2a12cd
+	[PGP_PUBKEY_RSA_ENC_ONLY]	= &RSA_public_key_algorithm,
Josh Boyer c2a12cd
+	[PGP_PUBKEY_RSA_SIG_ONLY]	= &RSA_public_key_algorithm,
Josh Boyer c2a12cd
+#endif
Josh Boyer c2a12cd
+	[PGP_PUBKEY_ELGAMAL]		= NULL,
Josh Boyer c2a12cd
+	[PGP_PUBKEY_DSA]		= NULL,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static const u8 pgp_public_key_capabilities[PGP_PUBKEY__LAST] = {
Josh Boyer c2a12cd
+	[PGP_PUBKEY_RSA_ENC_OR_SIG]	= PKEY_CAN_ENCDEC | PKEY_CAN_SIGVER,
Josh Boyer c2a12cd
+	[PGP_PUBKEY_RSA_ENC_ONLY]	= PKEY_CAN_ENCDEC,
Josh Boyer c2a12cd
+	[PGP_PUBKEY_RSA_SIG_ONLY]	= PKEY_CAN_SIGVER,
Josh Boyer c2a12cd
+	[PGP_PUBKEY_ELGAMAL]		= 0,
Josh Boyer c2a12cd
+	[PGP_PUBKEY_DSA]		= 0,
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+static inline void digest_putc(struct shash_desc *digest, uint8_t ch)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	crypto_shash_update(digest, &ch, 1);
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+struct pgp_key_data_parse_context {
Josh Boyer c2a12cd
+	struct pgp_parse_context pgp;
Josh Boyer c2a12cd
+	struct crypto_key_subtype *subtype;
Josh Boyer c2a12cd
+	char *fingerprint;
Josh Boyer c2a12cd
+	void *payload;
Josh Boyer c2a12cd
+};
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Calculate the public key ID (RFC4880 12.2)
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int pgp_calc_pkey_keyid(struct shash_desc *digest,
Josh Boyer c2a12cd
+			       struct pgp_parse_pubkey *pgp,
Josh Boyer c2a12cd
+			       struct public_key *key)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	unsigned nb[ARRAY_SIZE(key->mpi)];
Josh Boyer c2a12cd
+	unsigned nn[ARRAY_SIZE(key->mpi)];
Josh Boyer c2a12cd
+	unsigned n;
Josh Boyer c2a12cd
+	u8 *pp[ARRAY_SIZE(key->mpi)];
Josh Boyer c2a12cd
+	u32 a32;
Josh Boyer c2a12cd
+	int npkey = key->algo->n_pub_mpi;
Josh Boyer c2a12cd
+	int i, ret = -ENOMEM;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	kenter("");
Josh Boyer c2a12cd
+
Josh Boyer 5a0e7f0
+	for (i = 0; i < ARRAY_SIZE(pp); i++)
Josh Boyer 5a0e7f0
+		pp[i] = NULL;
Josh Boyer 5a0e7f0
+
Josh Boyer c2a12cd
+	n = (pgp->version < PGP_KEY_VERSION_4) ? 8 : 6;
Josh Boyer c2a12cd
+	for (i = 0; i < npkey; i++) {
Josh Boyer c2a12cd
+		nb[i] = mpi_get_nbits(key->mpi[i]);
Josh Boyer c2a12cd
+		pp[i] = mpi_get_buffer(key->mpi[i], nn + i, NULL);
Josh Boyer c2a12cd
+		if (!pp[i])
Josh Boyer c2a12cd
+			goto error;
Josh Boyer c2a12cd
+		n += 2 + nn[i];
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	digest_putc(digest, 0x99);     /* ctb */
Josh Boyer c2a12cd
+	digest_putc(digest, n >> 8);   /* 16-bit header length */
Josh Boyer c2a12cd
+	digest_putc(digest, n);
Josh Boyer c2a12cd
+	digest_putc(digest, pgp->version);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	a32 = pgp->creation_time;
Josh Boyer c2a12cd
+	digest_putc(digest, a32 >> 24);
Josh Boyer c2a12cd
+	digest_putc(digest, a32 >> 16);
Josh Boyer c2a12cd
+	digest_putc(digest, a32 >>  8);
Josh Boyer c2a12cd
+	digest_putc(digest, a32 >>  0);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	if (pgp->version < PGP_KEY_VERSION_4) {
Josh Boyer c2a12cd
+		u16 a16;
Josh Boyer c2a12cd
+
Josh Boyer 5a0e7f0
+		if (pgp->expires_at)
Josh Boyer c2a12cd
+			a16 = (pgp->expires_at - pgp->creation_time) / 86400UL;
Josh Boyer c2a12cd
+		else
Josh Boyer c2a12cd
+			a16 = 0;
Josh Boyer c2a12cd
+		digest_putc(digest, a16 >> 8);
Josh Boyer c2a12cd
+		digest_putc(digest, a16 >> 0);
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	digest_putc(digest, pgp->pubkey_algo);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	for (i = 0; i < npkey; i++) {
Josh Boyer c2a12cd
+		digest_putc(digest, nb[i] >> 8);
Josh Boyer c2a12cd
+		digest_putc(digest, nb[i]);
Josh Boyer c2a12cd
+		crypto_shash_update(digest, pp[i], nn[i]);
Josh Boyer c2a12cd
+	}
Josh Boyer c2a12cd
+	ret = 0;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+error:
Josh Boyer c2a12cd
+	for (i = 0; i < npkey; i++)
Josh Boyer c2a12cd
+		kfree(pp[i]);
Josh Boyer c2a12cd
+	kleave(" = %d", ret);
Josh Boyer c2a12cd
+	return ret;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Calculate the public key ID fingerprint
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx,
Josh Boyer c2a12cd
+				    struct pgp_parse_pubkey *pgp,
Josh Boyer c2a12cd
+				    struct public_key *key)
Josh Boyer c2a12cd
+{
Josh Boyer c2a12cd
+	struct crypto_shash *tfm;
Josh Boyer c2a12cd
+	struct shash_desc *digest;
Josh Boyer c2a12cd
+	char *fingerprint;
Josh Boyer c2a12cd
+	u8 *raw_fingerprint;
Josh Boyer c2a12cd
+	int digest_size, offset;
Josh Boyer c2a12cd
+	int ret, i;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	ret = -ENOMEM;
Josh Boyer c2a12cd
+	tfm = crypto_alloc_shash(pgp->version < PGP_KEY_VERSION_4 ?
Josh Boyer c2a12cd
+				 "md5" : "sha1", 0, 0);
Josh Boyer c2a12cd
+	if (!tfm)
Josh Boyer c2a12cd
+		goto cleanup;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	digest = kmalloc(sizeof(*digest) + crypto_shash_descsize(tfm),
Josh Boyer c2a12cd
+			 GFP_KERNEL);
Josh Boyer c2a12cd
+	if (!digest)
Josh Boyer c2a12cd
+		goto cleanup_tfm;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	digest->tfm = tfm;
Josh Boyer c2a12cd
+	digest->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
Josh Boyer c2a12cd
+	ret = crypto_shash_init(digest);
Josh Boyer c2a12cd
+	if (ret < 0)
Josh Boyer c2a12cd
+		goto cleanup_hash;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	ret = pgp_calc_pkey_keyid(digest, pgp, key);
Josh Boyer c2a12cd
+	if (ret < 0)
Josh Boyer c2a12cd
+		goto cleanup_hash;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	digest_size = crypto_shash_digestsize(tfm);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	raw_fingerprint = kmalloc(digest_size, GFP_KERNEL);
Josh Boyer c2a12cd
+	if (!raw_fingerprint)
Josh Boyer c2a12cd
+		goto cleanup_hash;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	ret = crypto_shash_final(digest, raw_fingerprint);
Josh Boyer c2a12cd
+	if (ret < 0)
Josh Boyer c2a12cd
+		goto cleanup_raw_fingerprint;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	fingerprint = kmalloc(digest_size * 2 + 1, GFP_KERNEL);
Josh Boyer c2a12cd
+	if (!fingerprint)
Josh Boyer c2a12cd
+		goto cleanup_raw_fingerprint;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	offset = digest_size - 8;
Josh Boyer c2a12cd
+	pr_debug("offset %u/%u\n", offset, digest_size);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	for (i = 0; i < digest_size; i++)
Josh Boyer c2a12cd
+		sprintf(fingerprint + i * 2, "%02x", raw_fingerprint[i]);
Josh Boyer c2a12cd
+	pr_debug("fingerprint %s\n", fingerprint);
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	memcpy(&key->key_id, raw_fingerprint + offset, 8);
Josh Boyer c2a12cd
+	key->key_id_size = 8;
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+	ctx->fingerprint = fingerprint;
Josh Boyer c2a12cd
+	ret = 0;
Josh Boyer c2a12cd
+cleanup_raw_fingerprint:
Josh Boyer c2a12cd
+	kfree(raw_fingerprint);
Josh Boyer c2a12cd
+cleanup_hash:
Josh Boyer c2a12cd
+	kfree(digest);
Josh Boyer c2a12cd
+cleanup_tfm:
Josh Boyer c2a12cd
+	crypto_free_shash(tfm);
Josh Boyer c2a12cd
+cleanup:
Josh Boyer c2a12cd
+	kleave(" = %d", ret);
Josh Boyer c2a12cd
+	return ret;
Josh Boyer c2a12cd
+}
Josh Boyer c2a12cd
+
Josh Boyer c2a12cd
+/*
Josh Boyer c2a12cd
+ * Extract a public key or public subkey from the PGP stream.
Josh Boyer c2a12cd
+ */
Josh Boyer c2a12cd
+static int pgp_process_public_key(struct pgp_parse_context *context,
</