[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

nss: CVE-2015-7181, CVE-2015-7182 and CVE-2015-4000 [was nss: CVE-2015-4000]



Hi,
On Wed, Nov 25, 2015 at 12:24:44PM +0100, Guido Günther wrote:
> Hi,
> I'm currently preparing fixes for nss and wonder if the security team
> already has a plan forward for CVE-2015-4000? Using the upstream patch
> would change defaults in a stable release. I think I'd be good to do the
> same for all currently supported releases.

Since there wasn't any feedback on this one I went ahead and prepared
upates for Squeeze, Wheezy and Jessie of CVE-2015-7181 and CVE-2015-7182
but skipped CVE-2015-4000 for now. I'm inclined to mark this as no-dsa
in Squeeze to not break existing installations.

I've attached the patches for review. These also add some minimal
autopkgtest to exercise the ASN1 parser (affected by the above CVEs).

I'm happy about any review.
Cheers,
 -- Guido
diff --git a/debian/changelog b/debian/changelog
index c5dad50..9891c21 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+nss (2:3.14.5-1+deb7u6) wheezy-security; urgency=medium
+
+  * Non-maintainer upload by the Security Team.
+  * Add CVE-2015-7182.patch:
+    CVE-2015-7182: Heap-based buffer overflow in the ASN.1 decoder
+  * Add CVE-2015-7181.patch:
+    CVE-2015-7181: The sec_asn1d_parse_leaf function improperly restricts
+    access to an unspecified data structure
+  * Add autopkgtest for certificate generation/signing and library linking
+
+ -- Guido Günther <agx@sigxcpu.org>  Sat, 28 Nov 2015 13:41:20 +0100
+
 nss (2:3.14.5-1+deb7u5) wheezy-security; urgency=high
 
   * Non-maintainer upload by the Security Team.
diff --git a/debian/patches/CVE-2015-7181.patch b/debian/patches/CVE-2015-7181.patch
new file mode 100644
index 0000000..98af810
--- /dev/null
+++ b/debian/patches/CVE-2015-7181.patch
@@ -0,0 +1,144 @@
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Mon, 23 Nov 2015 14:46:56 +0100
+Subject: CVE-2015-7181
+
+Consisting of upstream commits
+
+    https://hg.mozilla.org/projects/nss/rev/8ac7f47eecbb
+    https://hg.mozilla.org/projects/nss/rev/25cb033147fd
+---
+ mozilla/security/nss/lib/util/secasn1d.c | 101 ++++++++++++++++++++++++++-----
+ 1 file changed, 86 insertions(+), 15 deletions(-)
+
+diff --git a/mozilla/security/nss/lib/util/secasn1d.c b/mozilla/security/nss/lib/util/secasn1d.c
+index 9a8e26f..ca16efc 100644
+--- a/mozilla/security/nss/lib/util/secasn1d.c
++++ b/mozilla/security/nss/lib/util/secasn1d.c
+@@ -954,12 +954,42 @@ sec_asn1d_parse_more_length (sec_asn1d_state *state,
+ }
+ 
+ 
++/*
++ * Helper function for sec_asn1d_prepare_for_contents.
++ * Checks that a value representing a number of bytes consumed can be
++ * subtracted from a remaining length. If so, returns PR_TRUE.
++ * Otherwise, sets the error SEC_ERROR_BAD_DER, indicates that there was a
++ * decoding error in the given SEC_ASN1DecoderContext, and returns PR_FALSE.
++ */
++static PRBool
++sec_asn1d_check_and_subtract_length (unsigned long *remaining,
++                                     unsigned long consumed,
++                                     SEC_ASN1DecoderContext *cx)
++{
++    PORT_Assert(remaining);
++    PORT_Assert(cx);
++    if (!remaining || !cx) {
++        PORT_SetError (SEC_ERROR_INVALID_ARGS);
++        cx->status = decodeError;
++        return PR_FALSE;
++    }
++    if (*remaining < consumed) {
++        PORT_SetError (SEC_ERROR_BAD_DER);
++        cx->status = decodeError;
++        return PR_FALSE;
++    }
++    *remaining -= consumed;
++    return PR_TRUE;
++}
++
++
+ static void
+ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+ {
+     SECItem *item;
+     PRArenaPool *poolp;
+     unsigned long alloc_len;
++    sec_asn1d_state *parent;
+ 
+ #ifdef DEBUG_ASN1D_STATES
+     {
+@@ -967,6 +997,62 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+                state->indefinite ? "indefinite" : "");
+     }
+ #endif
++    /**
++     * The maximum length for a child element should be constrained to the
++     * length remaining in the first definite length element in the ancestor
++     * stack. If there is no definite length element in the ancestor stack,
++     * there's nothing to constrain the length of the child, so there's no
++     * further processing necessary.
++     *
++     * It's necessary to walk the ancestor stack, because it's possible to have
++     * definite length children that are part of an indefinite length element,
++     * which is itself part of an indefinite length element, and which is
++     * ultimately part of a definite length element. A simple example of this
++     * would be the handling of constructed OCTET STRINGs in BER encoding.
++     *
++     * This algorithm finds the first definite length element in the ancestor
++     * stack, if any, and if so, ensures that the length of the child element
++     * is consistent with the number of bytes remaining in the constraining
++     * ancestor element (that is, after accounting for any other sibling
++     * elements that may have been read).
++     *
++     * It's slightly complicated by the need to account both for integer
++     * underflow and overflow, as well as ensure that for indefinite length
++     * encodings, there's also enough space for the End-of-Contents (EOC)
++     * octets (Tag = 0x00, Length = 0x00, or two bytes).
++     */
++
++    /* Determine the maximum length available for this element by finding the
++     * first definite length ancestor, if any. */
++    parent = sec_asn1d_get_enclosing_construct(state);
++    while (parent && parent->indefinite) {
++        parent = sec_asn1d_get_enclosing_construct(parent);
++    }
++    /* If parent is null, state is either the outermost state / at the top of
++     * the stack, or the outermost state uses indefinite length encoding. In
++     * these cases, there's nothing external to constrain this element, so
++     * there's nothing to check. */
++    if (parent) {
++        unsigned long remaining = parent->pending;
++        parent = state;
++        do {
++            if (!sec_asn1d_check_and_subtract_length(
++                     &remaining, parent->consumed, state->top) ||
++                /* If parent->indefinite is true, parent->contents_length is
++                 * zero and this is a no-op. */
++                !sec_asn1d_check_and_subtract_length(
++                     &remaining, parent->contents_length, state->top) ||
++                /* If parent->indefinite is true, then ensure there is enough
++                 * space for an EOC tag of 2 bytes. */
++                (parent->indefinite && !sec_asn1d_check_and_subtract_length(
++                                            &remaining, 2, state->top))) {
++                /* This element is larger than its enclosing element, which is
++                 * invalid. */
++                return;
++            }
++        } while ((parent = sec_asn1d_get_enclosing_construct(parent)) &&
++                 parent->indefinite);
++    }
+ 
+     /*
+      * XXX I cannot decide if this allocation should exclude the case
+@@ -1009,21 +1095,6 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+      */
+     state->pending = state->contents_length;
+ 
+-    /* If this item has definite length encoding, and 
+-    ** is enclosed by a definite length constructed type,
+-    ** make sure it isn't longer than the remaining space in that 
+-    ** constructed type.  
+-    */
+-    if (state->contents_length > 0) {
+-	sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state);
+-	if (parent && !parent->indefinite && 
+-	    state->consumed + state->contents_length > parent->pending) {
+-	    PORT_SetError (SEC_ERROR_BAD_DER);
+-	    state->top->status = decodeError;
+-	    return;
+-	}
+-    }
+-
+     /*
+      * An EXPLICIT is nothing but an outer header, which we have
+      * already parsed and accepted.  Now we need to do the inner
diff --git a/debian/patches/CVE-2015-7182.patch b/debian/patches/CVE-2015-7182.patch
new file mode 100644
index 0000000..cf95486
--- /dev/null
+++ b/debian/patches/CVE-2015-7182.patch
@@ -0,0 +1,126 @@
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Mon, 23 Nov 2015 11:20:50 +0100
+Subject: CVE-2015-7182
+
+Consisting of upstream commits
+
+    https://hg.mozilla.org/projects/nss/raw-rev/4dc247276e58
+    https://hg.mozilla.org/projects/nss/raw-rev/534aca7a5bca
+    https://hg.mozilla.org/projects/nss/raw-rev/b4feb2cb0ed6
+---
+ mozilla/security/nss/lib/util/secasn1d.c | 99 +++++++++++++++++++++++++++++++-
+ 1 file changed, 98 insertions(+), 1 deletion(-)
+
+diff --git a/mozilla/security/nss/lib/util/secasn1d.c b/mozilla/security/nss/lib/util/secasn1d.c
+index 6c3d2e9..9a8e26f 100644
+--- a/mozilla/security/nss/lib/util/secasn1d.c
++++ b/mozilla/security/nss/lib/util/secasn1d.c
+@@ -1722,10 +1722,107 @@ sec_asn1d_next_substring (sec_asn1d_state *state)
+ 	if (state->pending == 0)
+ 	    done = PR_TRUE;
+     } else {
++	PRBool preallocatedString;
++	sec_asn1d_state *temp_state;
+ 	PORT_Assert (state->indefinite);
+ 
+ 	item = (SECItem *)(child->dest);
+-	if (item != NULL && item->data != NULL) {
++
++	/**
++	 * At this point, there's three states at play:
++	 *   child: The element that was just parsed
++	 *   state: The currently processed element
++	 *   'parent' (aka state->parent): The enclosing construct
++	 *      of state, or NULL if this is the top-most element.
++	 *
++	 * This state handles both substrings of a constructed string AND
++	 * child elements of items whose template type was that of
++	 * SEC_ASN1_ANY, SEC_ASN1_SAVE, SEC_ASN1_ANY_CONTENTS, SEC_ASN1_SKIP
++	 * template, as described in sec_asn1d_prepare_for_contents. For
++	 * brevity, these will be referred to as 'string' and 'any' types.
++	 *
++	 * This leads to the following possibilities:
++	 *   1: This element is an indefinite length string, part of a
++	 *      definite length string.
++	 *   2: This element is an indefinite length string, part of an
++	 *      indefinite length string.
++	 *   3: This element is an indefinite length any, part of a
++	 *      definite length any.
++	 *   4: This element is an indefinite length any, part of an
++	 *      indefinite length any.
++	 *   5: This element is an indefinite length any and does not
++	 *      meet any of the above criteria. Note that this would include
++	 *      an indefinite length string type matching an indefinite
++	 *      length any template.
++	 *
++	 * In Cases #1 and #3, the definite length 'parent' element will
++	 * have allocated state->dest based on the parent elements definite
++	 * size. During the processing of 'child', sec_asn1d_parse_leaf will
++	 * have copied the (string, any) data directly into the offset of
++	 * dest, as appropriate, so there's no need for this class to still
++	 * store the child - it's already been processed.
++	 *
++	 * In Cases #2 and #4, dest will be set to the parent element's dest,
++	 * but dest->data will not have been allocated yet, due to the
++	 * indefinite length encoding. In this situation, it's necessary to
++	 * hold onto child (and all other children) until the EOC, at which
++	 * point, it becomes possible to compute 'state's overall length. Once
++	 * 'state' has a computed length, this can then be fed to 'parent' (via
++	 * this state), and then 'parent' can similarly compute the length of
++	 * all of its children up to the EOC, which will ultimately transit to
++	 * sec_asn1d_concat_substrings, determine the overall size needed,
++	 * allocate, and copy the contents (of all of parent's children, which
++	 * would include 'state', just as 'state' will have copied all of its
++	 * children via sec_asn1d_concat_substrings)
++	 *
++	 * The final case, Case #5, will manifest in that item->data and
++	 * item->len will be NULL/0, respectively, since this element was
++	 * indefinite-length encoded. In that case, both the tag and length will
++	 * already exist in state's subitems, via sec_asn1d_record_any_header,
++	 * and so the contents (aka 'child') should be added to that list of
++	 * items to concatenate in sec_asn1d_concat_substrings once the EOC
++	 * is encountered.
++	 *
++	 * To distinguish #2/#4 from #1/#3, it's sufficient to walk the ancestor
++	 * tree. If the current type is a string type, then the enclosing
++	 * construct will be that same type (#1/#2). If the current type is an
++	 * any type, then the enclosing construct is either an any type (#3/#4)
++	 * or some other type (#5). Since this is BER, this nesting relationship
++	 * between 'state' and 'parent' may go through several levels of
++	 * constructed encoding, so continue walking the ancestor chain until a
++	 * clear determination can be made.
++	 *
++	 * The variable preallocatedString is used to indicate Case #1/#3,
++	 * indicating an in-place copy has already occurred, and Cases #2, #4,
++	 * and #5 all have the same behaviour of adding a new substring.
++	 */
++	preallocatedString = PR_FALSE;
++	temp_state = state;
++	while (temp_state && item == temp_state->dest && temp_state->indefinite) {
++	    sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(temp_state);
++	    if (!parent || parent->underlying_kind != temp_state->underlying_kind) {
++	        /* Case #5 - Either this is a top-level construct or it is part
++	         * of some other element (e.g. a SEQUENCE), in which case, a
++	         * new item should be allocated. */
++	        break;
++	    }
++	    if (!parent->indefinite) {
++	        /* Cases #1 / #3 - A definite length ancestor exists, for which
++	         * this is a substring that has already copied into dest. */
++	        preallocatedString = PR_TRUE;
++	        break;
++	    }
++	    if (!parent->substring) {
++	        /* Cases #2 / #4 - If the parent is not a substring, but is
++	         * indefinite, then there's nothing further up that may have
++	         * preallocated dest, thus child will not have already
++		 * been copied in place, therefore it's necessary to save child
++		 * as a subitem. */
++	        break;
++	    }
++	    temp_state = parent;
++	}
++	if (item != NULL && item->data != NULL && !preallocatedString) {
+ 	    /*
+ 	     * Save the string away for later concatenation.
+ 	     */
diff --git a/debian/patches/series b/debian/patches/series
index f4273b6..f69d529 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -14,3 +14,5 @@ CVE-2014-1544.patch
 CVE-2014-1569.patch
 CVE-2015-2721.patch
 CVE-2015-2730.patch
+CVE-2015-7182.patch
+CVE-2015-7181.patch
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 0000000..1b3d995
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,5 @@
+Tests: test-cert.sh
+Depends: libnss3-tools
+
+Tests: test-link.make
+Depends: libnss3-dev, pkg-config, g++
diff --git a/debian/tests/test-cert.sh b/debian/tests/test-cert.sh
new file mode 100644
index 0000000..14c0907
--- /dev/null
+++ b/debian/tests/test-cert.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+#
+# Check some basic CA operations
+
+set -e
+
+cleanup() {
+    [ -z "$DIR" ] || rm -rf "$DIR"
+}
+
+
+run_certutil() {
+    CMD="certutil -z $DIR/random -f $DIR/passwd -d sql:$DIR $@"
+    echo "Running: $CMD"
+    $CMD
+}
+
+DIR=`mktemp -p . -d`
+#trap cleanup EXIT ERR
+
+dd  bs=20 count=1 if=/dev/urandom of=$DIR/random 2>/dev/null
+echo "password" > $DIR/passwd
+
+# Create the database
+run_certutil -N
+# Create a self signed certificate
+run_certutil -S -k rsa -n test-ca -s CN=testca -t c -x 2>/dev/null
+# Create a certificate request
+run_certutil -R -k rsa -g 2048 -n test-cert -s "CN=testcert" -o $DIR/cert.req -a 2>/dev/null
+# Sign with ca
+run_certutil -C -m 10000 -c test-ca -i $DIR/cert.req -o $DIR/cert.cer -a
+run_certutil -A -n test-cert -i $DIR/cert.cer -t c -a
+
+echo -n "Checking if ca is present..."
+run_certutil -L -n test-ca >/dev/null
+echo "OK."
+
+echo -n "Checking if cert present..."
+run_certutil -L -n test-cert >/dev/null
+echo "OK."
+
+exit 0
diff --git a/debian/tests/test-link.cpp b/debian/tests/test-link.cpp
new file mode 100644
index 0000000..0880b4e
--- /dev/null
+++ b/debian/tests/test-link.cpp
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <nss.h>
+
+int main()
+{
+  int ret = 0;
+  SECStatus s;
+  char *t = strdup("/tmp/nss.XXXXXX");
+  char *tmpdir = mkdtemp(t);
+
+  if (tmpdir == NULL)
+    fprintf(stderr, "Failed to create temp directory: %s", strerror(errno));
+  
+  s = NSS_InitReadWrite(tmpdir);
+  if (s != SECSuccess)
+    ret = 2;
+  
+  NSS_Shutdown();
+  free(t);
+
+  return ret;
+}
diff --git a/debian/tests/test-link.make b/debian/tests/test-link.make
new file mode 100755
index 0000000..19e4e7c
--- /dev/null
+++ b/debian/tests/test-link.make
@@ -0,0 +1,10 @@
+#!/usr/bin/make -f
+
+all: a.out
+	./a.out
+	rm -f a.out
+
+a.out: debian/tests/test-link.cpp
+	g++ -Wall -Werror $<  $(shell pkg-config --cflags nss) $(shell pkg-config --libs nss)
+
+.PHONY: all
diff --git a/debian/changelog b/debian/changelog
index cb86f1f..dd8e5b5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+nss (2:3.17.2-1.1+deb8u3) jessie; urgency=medium
+
+  * Non-maintainer upload by the Security Team.
+  * Add CVE-2015-7182.patch:
+    CVE-2015-7182: Heap-based buffer overflow in the ASN.1 decoder
+  * Add CVE-2015-7181.patch:
+    CVE-2015-7181: The sec_asn1d_parse_leaf function improperly restricts
+    access to an unspecified data structure
+  * Add autopkgtest for certificate generation/signing and library linking
+
+ -- Guido Günther <agx@sigxcpu.org>  Sat, 28 Nov 2015 14:04:34 +0100
+
 nss (2:3.17.2-1.1+deb8u2) jessie; urgency=medium
 
   [ Andrew Ayer ]
diff --git a/debian/patches/CVE-2015-7181.patch b/debian/patches/CVE-2015-7181.patch
new file mode 100644
index 0000000..6cfd3b0
--- /dev/null
+++ b/debian/patches/CVE-2015-7181.patch
@@ -0,0 +1,145 @@
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Mon, 23 Nov 2015 14:46:56 +0100
+Subject: CVE-2015-7181
+
+Consisting of upstream commits
+
+    https://hg.mozilla.org/projects/nss/rev/8ac7f47eecbb
+    https://hg.mozilla.org/projects/nss/rev/25cb033147fd
+---
+ nss/lib/util/secasn1d.c | 101 +++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 86 insertions(+), 15 deletions(-)
+
+diff --git a/nss/lib/util/secasn1d.c b/nss/lib/util/secasn1d.c
+index 4cdae36..43bf3d8 100644
+--- a/nss/lib/util/secasn1d.c
++++ b/nss/lib/util/secasn1d.c
+@@ -951,6 +951,35 @@ sec_asn1d_parse_more_length (sec_asn1d_state *state,
+     return count;
+ }
+ 
++/*
++ * Helper function for sec_asn1d_prepare_for_contents.
++ * Checks that a value representing a number of bytes consumed can be
++ * subtracted from a remaining length. If so, returns PR_TRUE.
++ * Otherwise, sets the error SEC_ERROR_BAD_DER, indicates that there was a
++ * decoding error in the given SEC_ASN1DecoderContext, and returns PR_FALSE.
++ */
++static PRBool
++sec_asn1d_check_and_subtract_length (unsigned long *remaining,
++                                     unsigned long consumed,
++                                     SEC_ASN1DecoderContext *cx)
++{
++    PORT_Assert(remaining);
++    PORT_Assert(cx);
++    if (!remaining || !cx) {
++        PORT_SetError (SEC_ERROR_INVALID_ARGS);
++        cx->status = decodeError;
++        return PR_FALSE;
++    }
++    if (*remaining < consumed) {
++        PORT_SetError (SEC_ERROR_BAD_DER);
++        cx->status = decodeError;
++        return PR_FALSE;
++    }
++    *remaining -= consumed;
++    return PR_TRUE;
++}
++
++
+ 
+ static void
+ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+@@ -958,6 +987,7 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+     SECItem *item;
+     PLArenaPool *poolp;
+     unsigned long alloc_len;
++    sec_asn1d_state *parent;
+ 
+ #ifdef DEBUG_ASN1D_STATES
+     {
+@@ -965,6 +995,62 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+                state->indefinite ? "indefinite" : "");
+     }
+ #endif
++    /**
++     * The maximum length for a child element should be constrained to the
++     * length remaining in the first definite length element in the ancestor
++     * stack. If there is no definite length element in the ancestor stack,
++     * there's nothing to constrain the length of the child, so there's no
++     * further processing necessary.
++     *
++     * It's necessary to walk the ancestor stack, because it's possible to have
++     * definite length children that are part of an indefinite length element,
++     * which is itself part of an indefinite length element, and which is
++     * ultimately part of a definite length element. A simple example of this
++     * would be the handling of constructed OCTET STRINGs in BER encoding.
++     *
++     * This algorithm finds the first definite length element in the ancestor
++     * stack, if any, and if so, ensures that the length of the child element
++     * is consistent with the number of bytes remaining in the constraining
++     * ancestor element (that is, after accounting for any other sibling
++     * elements that may have been read).
++     *
++     * It's slightly complicated by the need to account both for integer
++     * underflow and overflow, as well as ensure that for indefinite length
++     * encodings, there's also enough space for the End-of-Contents (EOC)
++     * octets (Tag = 0x00, Length = 0x00, or two bytes).
++     */
++
++    /* Determine the maximum length available for this element by finding the
++     * first definite length ancestor, if any. */
++    parent = sec_asn1d_get_enclosing_construct(state);
++    while (parent && parent->indefinite) {
++        parent = sec_asn1d_get_enclosing_construct(parent);
++    }
++    /* If parent is null, state is either the outermost state / at the top of
++     * the stack, or the outermost state uses indefinite length encoding. In
++     * these cases, there's nothing external to constrain this element, so
++     * there's nothing to check. */
++    if (parent) {
++        unsigned long remaining = parent->pending;
++        parent = state;
++        do {
++            if (!sec_asn1d_check_and_subtract_length(
++                     &remaining, parent->consumed, state->top) ||
++                /* If parent->indefinite is true, parent->contents_length is
++                 * zero and this is a no-op. */
++                !sec_asn1d_check_and_subtract_length(
++                     &remaining, parent->contents_length, state->top) ||
++                /* If parent->indefinite is true, then ensure there is enough
++                 * space for an EOC tag of 2 bytes. */
++                (parent->indefinite && !sec_asn1d_check_and_subtract_length(
++                                            &remaining, 2, state->top))) {
++                /* This element is larger than its enclosing element, which is
++                 * invalid. */
++                return;
++            }
++        } while ((parent = sec_asn1d_get_enclosing_construct(parent)) &&
++                 parent->indefinite);
++    }
+ 
+     /*
+      * XXX I cannot decide if this allocation should exclude the case
+@@ -1007,21 +1093,6 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+      */
+     state->pending = state->contents_length;
+ 
+-    /* If this item has definite length encoding, and 
+-    ** is enclosed by a definite length constructed type,
+-    ** make sure it isn't longer than the remaining space in that 
+-    ** constructed type.  
+-    */
+-    if (state->contents_length > 0) {
+-	sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state);
+-	if (parent && !parent->indefinite && 
+-	    state->consumed + state->contents_length > parent->pending) {
+-	    PORT_SetError (SEC_ERROR_BAD_DER);
+-	    state->top->status = decodeError;
+-	    return;
+-	}
+-    }
+-
+     /*
+      * An EXPLICIT is nothing but an outer header, which we have
+      * already parsed and accepted.  Now we need to do the inner
diff --git a/debian/patches/CVE-2015-7182.patch b/debian/patches/CVE-2015-7182.patch
new file mode 100644
index 0000000..5ca35d4
--- /dev/null
+++ b/debian/patches/CVE-2015-7182.patch
@@ -0,0 +1,126 @@
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Mon, 23 Nov 2015 11:20:50 +0100
+Subject: CVE-2015-7182
+
+Consisting of upstream commits
+
+    https://hg.mozilla.org/projects/nss/raw-rev/4dc247276e58
+    https://hg.mozilla.org/projects/nss/raw-rev/534aca7a5bca
+    https://hg.mozilla.org/projects/nss/raw-rev/b4feb2cb0ed6
+---
+ nss/lib/util/secasn1d.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 98 insertions(+), 1 deletion(-)
+
+diff --git a/nss/lib/util/secasn1d.c b/nss/lib/util/secasn1d.c
+index d404b72..4cdae36 100644
+--- a/nss/lib/util/secasn1d.c
++++ b/nss/lib/util/secasn1d.c
+@@ -1720,10 +1720,107 @@ sec_asn1d_next_substring (sec_asn1d_state *state)
+ 	if (state->pending == 0)
+ 	    done = PR_TRUE;
+     } else {
++	PRBool preallocatedString;
++	sec_asn1d_state *temp_state;
+ 	PORT_Assert (state->indefinite);
+ 
+ 	item = (SECItem *)(child->dest);
+-	if (item != NULL && item->data != NULL) {
++
++	/**
++	 * At this point, there's three states at play:
++	 *   child: The element that was just parsed
++	 *   state: The currently processed element
++	 *   'parent' (aka state->parent): The enclosing construct
++	 *      of state, or NULL if this is the top-most element.
++	 *
++	 * This state handles both substrings of a constructed string AND
++	 * child elements of items whose template type was that of
++	 * SEC_ASN1_ANY, SEC_ASN1_SAVE, SEC_ASN1_ANY_CONTENTS, SEC_ASN1_SKIP
++	 * template, as described in sec_asn1d_prepare_for_contents. For
++	 * brevity, these will be referred to as 'string' and 'any' types.
++	 *
++	 * This leads to the following possibilities:
++	 *   1: This element is an indefinite length string, part of a
++	 *      definite length string.
++	 *   2: This element is an indefinite length string, part of an
++	 *      indefinite length string.
++	 *   3: This element is an indefinite length any, part of a
++	 *      definite length any.
++	 *   4: This element is an indefinite length any, part of an
++	 *      indefinite length any.
++	 *   5: This element is an indefinite length any and does not
++	 *      meet any of the above criteria. Note that this would include
++	 *      an indefinite length string type matching an indefinite
++	 *      length any template.
++	 *
++	 * In Cases #1 and #3, the definite length 'parent' element will
++	 * have allocated state->dest based on the parent elements definite
++	 * size. During the processing of 'child', sec_asn1d_parse_leaf will
++	 * have copied the (string, any) data directly into the offset of
++	 * dest, as appropriate, so there's no need for this class to still
++	 * store the child - it's already been processed.
++	 *
++	 * In Cases #2 and #4, dest will be set to the parent element's dest,
++	 * but dest->data will not have been allocated yet, due to the
++	 * indefinite length encoding. In this situation, it's necessary to
++	 * hold onto child (and all other children) until the EOC, at which
++	 * point, it becomes possible to compute 'state's overall length. Once
++	 * 'state' has a computed length, this can then be fed to 'parent' (via
++	 * this state), and then 'parent' can similarly compute the length of
++	 * all of its children up to the EOC, which will ultimately transit to
++	 * sec_asn1d_concat_substrings, determine the overall size needed,
++	 * allocate, and copy the contents (of all of parent's children, which
++	 * would include 'state', just as 'state' will have copied all of its
++	 * children via sec_asn1d_concat_substrings)
++	 *
++	 * The final case, Case #5, will manifest in that item->data and
++	 * item->len will be NULL/0, respectively, since this element was
++	 * indefinite-length encoded. In that case, both the tag and length will
++	 * already exist in state's subitems, via sec_asn1d_record_any_header,
++	 * and so the contents (aka 'child') should be added to that list of
++	 * items to concatenate in sec_asn1d_concat_substrings once the EOC
++	 * is encountered.
++	 *
++	 * To distinguish #2/#4 from #1/#3, it's sufficient to walk the ancestor
++	 * tree. If the current type is a string type, then the enclosing
++	 * construct will be that same type (#1/#2). If the current type is an
++	 * any type, then the enclosing construct is either an any type (#3/#4)
++	 * or some other type (#5). Since this is BER, this nesting relationship
++	 * between 'state' and 'parent' may go through several levels of
++	 * constructed encoding, so continue walking the ancestor chain until a
++	 * clear determination can be made.
++	 *
++	 * The variable preallocatedString is used to indicate Case #1/#3,
++	 * indicating an in-place copy has already occurred, and Cases #2, #4,
++	 * and #5 all have the same behaviour of adding a new substring.
++	 */
++	preallocatedString = PR_FALSE;
++	temp_state = state;
++	while (temp_state && item == temp_state->dest && temp_state->indefinite) {
++	    sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(temp_state);
++	    if (!parent || parent->underlying_kind != temp_state->underlying_kind) {
++	        /* Case #5 - Either this is a top-level construct or it is part
++	         * of some other element (e.g. a SEQUENCE), in which case, a
++	         * new item should be allocated. */
++	        break;
++	    }
++	    if (!parent->indefinite) {
++	        /* Cases #1 / #3 - A definite length ancestor exists, for which
++	         * this is a substring that has already copied into dest. */
++	        preallocatedString = PR_TRUE;
++	        break;
++	    }
++	    if (!parent->substring) {
++	        /* Cases #2 / #4 - If the parent is not a substring, but is
++	         * indefinite, then there's nothing further up that may have
++	         * preallocated dest, thus child will not have already
++		 * been copied in place, therefore it's necessary to save child
++		 * as a subitem. */
++	        break;
++	    }
++	    temp_state = parent;
++	}
++	if (item != NULL && item->data != NULL && !preallocatedString) {
+ 	    /*
+ 	     * Save the string away for later concatenation.
+ 	     */
diff --git a/debian/patches/series b/debian/patches/series
index 7f899ec..93ce559 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -8,3 +8,5 @@
 99_CVE-2015-2721.patch
 100_CVE-2015-2730.patch
 101_prefer_stronger_cert_chains.patch
+CVE-2015-7182.patch
+CVE-2015-7181.patch
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 0000000..1b3d995
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,5 @@
+Tests: test-cert.sh
+Depends: libnss3-tools
+
+Tests: test-link.make
+Depends: libnss3-dev, pkg-config, g++
diff --git a/debian/tests/test-cert.sh b/debian/tests/test-cert.sh
new file mode 100644
index 0000000..14c0907
--- /dev/null
+++ b/debian/tests/test-cert.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+#
+# Check some basic CA operations
+
+set -e
+
+cleanup() {
+    [ -z "$DIR" ] || rm -rf "$DIR"
+}
+
+
+run_certutil() {
+    CMD="certutil -z $DIR/random -f $DIR/passwd -d sql:$DIR $@"
+    echo "Running: $CMD"
+    $CMD
+}
+
+DIR=`mktemp -p . -d`
+#trap cleanup EXIT ERR
+
+dd  bs=20 count=1 if=/dev/urandom of=$DIR/random 2>/dev/null
+echo "password" > $DIR/passwd
+
+# Create the database
+run_certutil -N
+# Create a self signed certificate
+run_certutil -S -k rsa -n test-ca -s CN=testca -t c -x 2>/dev/null
+# Create a certificate request
+run_certutil -R -k rsa -g 2048 -n test-cert -s "CN=testcert" -o $DIR/cert.req -a 2>/dev/null
+# Sign with ca
+run_certutil -C -m 10000 -c test-ca -i $DIR/cert.req -o $DIR/cert.cer -a
+run_certutil -A -n test-cert -i $DIR/cert.cer -t c -a
+
+echo -n "Checking if ca is present..."
+run_certutil -L -n test-ca >/dev/null
+echo "OK."
+
+echo -n "Checking if cert present..."
+run_certutil -L -n test-cert >/dev/null
+echo "OK."
+
+exit 0
diff --git a/debian/tests/test-link.cpp b/debian/tests/test-link.cpp
new file mode 100644
index 0000000..0880b4e
--- /dev/null
+++ b/debian/tests/test-link.cpp
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <nss.h>
+
+int main()
+{
+  int ret = 0;
+  SECStatus s;
+  char *t = strdup("/tmp/nss.XXXXXX");
+  char *tmpdir = mkdtemp(t);
+
+  if (tmpdir == NULL)
+    fprintf(stderr, "Failed to create temp directory: %s", strerror(errno));
+  
+  s = NSS_InitReadWrite(tmpdir);
+  if (s != SECSuccess)
+    ret = 2;
+  
+  NSS_Shutdown();
+  free(t);
+
+  return ret;
+}
diff --git a/debian/tests/test-link.make b/debian/tests/test-link.make
new file mode 100755
index 0000000..19e4e7c
--- /dev/null
+++ b/debian/tests/test-link.make
@@ -0,0 +1,10 @@
+#!/usr/bin/make -f
+
+all: a.out
+	./a.out
+	rm -f a.out
+
+a.out: debian/tests/test-link.cpp
+	g++ -Wall -Werror $<  $(shell pkg-config --cflags nss) $(shell pkg-config --libs nss)
+
+.PHONY: all
diff --git a/debian/changelog b/debian/changelog
index be0888f..e707c87 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,16 @@
+nss (3.12.8-1+squeeze13) squeeze-lts; urgency=medium
+
+  * Non-maintainer upload by the Debian LTS Team.
+  * Add CVE-2015-7182.patch:
+    CVE-2015-7182: Heap-based buffer overflow in the ASN.1 decoder
+  * Add CVE-2015-7181.patch:
+  * CVE-2015-7181: The sec_asn1d_parse_leaf function improperly restricts
+    access to an unspecified data structure
+  * Add autopkgtest for certificate generation/signing and library linking
+  * Add gbp.conf for LTS
+
+ -- Guido Günther <agx@sigxcpu.org>  Sat, 28 Nov 2015 12:42:04 +0100
+
 nss (3.12.8-1+squeeze12) squeeze-lts; urgency=medium
 
   * Non-maintainer upload by the Debian LTS Team.
diff --git a/debian/gbp.conf b/debian/gbp.conf
new file mode 100644
index 0000000..bc808da
--- /dev/null
+++ b/debian/gbp.conf
@@ -0,0 +1,5 @@
+[DEFAULT]
+debian-branch = debian/squeeze-lts
+
+[dch]
+id-length = 0
diff --git a/debian/patches/CVE-2015-7181.patch b/debian/patches/CVE-2015-7181.patch
new file mode 100644
index 0000000..a12c8c6
--- /dev/null
+++ b/debian/patches/CVE-2015-7181.patch
@@ -0,0 +1,144 @@
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Mon, 23 Nov 2015 14:46:56 +0100
+Subject: CVE-2015-7181
+
+Consisting of upstream commits
+
+    https://hg.mozilla.org/projects/nss/rev/8ac7f47eecbb
+    https://hg.mozilla.org/projects/nss/rev/25cb033147fd
+---
+ mozilla/security/nss/lib/util/secasn1d.c | 101 ++++++++++++++++++++++++++-----
+ 1 file changed, 86 insertions(+), 15 deletions(-)
+
+diff --git a/mozilla/security/nss/lib/util/secasn1d.c b/mozilla/security/nss/lib/util/secasn1d.c
+index 1b4bad8..0f7d97a 100644
+--- a/mozilla/security/nss/lib/util/secasn1d.c
++++ b/mozilla/security/nss/lib/util/secasn1d.c
+@@ -986,12 +986,42 @@ sec_asn1d_parse_more_length (sec_asn1d_state *state,
+ }
+ 
+ 
++/*
++ * Helper function for sec_asn1d_prepare_for_contents.
++ * Checks that a value representing a number of bytes consumed can be
++ * subtracted from a remaining length. If so, returns PR_TRUE.
++ * Otherwise, sets the error SEC_ERROR_BAD_DER, indicates that there was a
++ * decoding error in the given SEC_ASN1DecoderContext, and returns PR_FALSE.
++ */
++static PRBool
++sec_asn1d_check_and_subtract_length (unsigned long *remaining,
++                                     unsigned long consumed,
++                                     SEC_ASN1DecoderContext *cx)
++{
++    PORT_Assert(remaining);
++    PORT_Assert(cx);
++    if (!remaining || !cx) {
++        PORT_SetError (SEC_ERROR_INVALID_ARGS);
++        cx->status = decodeError;
++        return PR_FALSE;
++    }
++    if (*remaining < consumed) {
++        PORT_SetError (SEC_ERROR_BAD_DER);
++        cx->status = decodeError;
++        return PR_FALSE;
++    }
++    *remaining -= consumed;
++    return PR_TRUE;
++}
++
++
+ static void
+ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+ {
+     SECItem *item;
+     PRArenaPool *poolp;
+     unsigned long alloc_len;
++    sec_asn1d_state *parent;
+ 
+ #ifdef DEBUG_ASN1D_STATES
+     {
+@@ -999,6 +1029,62 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+                state->indefinite ? "indefinite" : "");
+     }
+ #endif
++    /**
++     * The maximum length for a child element should be constrained to the
++     * length remaining in the first definite length element in the ancestor
++     * stack. If there is no definite length element in the ancestor stack,
++     * there's nothing to constrain the length of the child, so there's no
++     * further processing necessary.
++     *
++     * It's necessary to walk the ancestor stack, because it's possible to have
++     * definite length children that are part of an indefinite length element,
++     * which is itself part of an indefinite length element, and which is
++     * ultimately part of a definite length element. A simple example of this
++     * would be the handling of constructed OCTET STRINGs in BER encoding.
++     *
++     * This algorithm finds the first definite length element in the ancestor
++     * stack, if any, and if so, ensures that the length of the child element
++     * is consistent with the number of bytes remaining in the constraining
++     * ancestor element (that is, after accounting for any other sibling
++     * elements that may have been read).
++     *
++     * It's slightly complicated by the need to account both for integer
++     * underflow and overflow, as well as ensure that for indefinite length
++     * encodings, there's also enough space for the End-of-Contents (EOC)
++     * octets (Tag = 0x00, Length = 0x00, or two bytes).
++     */
++
++    /* Determine the maximum length available for this element by finding the
++     * first definite length ancestor, if any. */
++    parent = sec_asn1d_get_enclosing_construct(state);
++    while (parent && parent->indefinite) {
++        parent = sec_asn1d_get_enclosing_construct(parent);
++    }
++    /* If parent is null, state is either the outermost state / at the top of
++     * the stack, or the outermost state uses indefinite length encoding. In
++     * these cases, there's nothing external to constrain this element, so
++     * there's nothing to check. */
++    if (parent) {
++        unsigned long remaining = parent->pending;
++        parent = state;
++        do {
++            if (!sec_asn1d_check_and_subtract_length(
++                     &remaining, parent->consumed, state->top) ||
++                /* If parent->indefinite is true, parent->contents_length is
++                 * zero and this is a no-op. */
++                !sec_asn1d_check_and_subtract_length(
++                     &remaining, parent->contents_length, state->top) ||
++                /* If parent->indefinite is true, then ensure there is enough
++                 * space for an EOC tag of 2 bytes. */
++                (parent->indefinite && !sec_asn1d_check_and_subtract_length(
++                                            &remaining, 2, state->top))) {
++                /* This element is larger than its enclosing element, which is
++                 * invalid. */
++                return;
++            }
++        } while ((parent = sec_asn1d_get_enclosing_construct(parent)) &&
++                 parent->indefinite);
++    }
+ 
+     /*
+      * XXX I cannot decide if this allocation should exclude the case
+@@ -1041,21 +1127,6 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+      */
+     state->pending = state->contents_length;
+ 
+-    /* If this item has definite length encoding, and 
+-    ** is enclosed by a definite length constructed type,
+-    ** make sure it isn't longer than the remaining space in that 
+-    ** constructed type.  
+-    */
+-    if (state->contents_length > 0) {
+-	sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state);
+-	if (parent && !parent->indefinite && 
+-	    state->consumed + state->contents_length > parent->pending) {
+-	    PORT_SetError (SEC_ERROR_BAD_DER);
+-	    state->top->status = decodeError;
+-	    return;
+-	}
+-    }
+-
+     /*
+      * An EXPLICIT is nothing but an outer header, which we have
+      * already parsed and accepted.  Now we need to do the inner
diff --git a/debian/patches/CVE-2015-7182.patch b/debian/patches/CVE-2015-7182.patch
new file mode 100644
index 0000000..9125d27
--- /dev/null
+++ b/debian/patches/CVE-2015-7182.patch
@@ -0,0 +1,126 @@
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
+Date: Mon, 23 Nov 2015 11:20:50 +0100
+Subject: CVE-2015-7182
+
+Consisting of upstream commits
+
+    https://hg.mozilla.org/projects/nss/raw-rev/4dc247276e58
+    https://hg.mozilla.org/projects/nss/raw-rev/534aca7a5bca
+    https://hg.mozilla.org/projects/nss/raw-rev/b4feb2cb0ed6
+---
+ mozilla/security/nss/lib/util/secasn1d.c | 99 +++++++++++++++++++++++++++++++-
+ 1 file changed, 98 insertions(+), 1 deletion(-)
+
+diff --git a/mozilla/security/nss/lib/util/secasn1d.c b/mozilla/security/nss/lib/util/secasn1d.c
+index a1323f2..1b4bad8 100644
+--- a/mozilla/security/nss/lib/util/secasn1d.c
++++ b/mozilla/security/nss/lib/util/secasn1d.c
+@@ -1754,10 +1754,107 @@ sec_asn1d_next_substring (sec_asn1d_state *state)
+ 	if (state->pending == 0)
+ 	    done = PR_TRUE;
+     } else {
++	PRBool preallocatedString;
++	sec_asn1d_state *temp_state;
+ 	PORT_Assert (state->indefinite);
+ 
+ 	item = (SECItem *)(child->dest);
+-	if (item != NULL && item->data != NULL) {
++
++	/**
++	 * At this point, there's three states at play:
++	 *   child: The element that was just parsed
++	 *   state: The currently processed element
++	 *   'parent' (aka state->parent): The enclosing construct
++	 *      of state, or NULL if this is the top-most element.
++	 *
++	 * This state handles both substrings of a constructed string AND
++	 * child elements of items whose template type was that of
++	 * SEC_ASN1_ANY, SEC_ASN1_SAVE, SEC_ASN1_ANY_CONTENTS, SEC_ASN1_SKIP
++	 * template, as described in sec_asn1d_prepare_for_contents. For
++	 * brevity, these will be referred to as 'string' and 'any' types.
++	 *
++	 * This leads to the following possibilities:
++	 *   1: This element is an indefinite length string, part of a
++	 *      definite length string.
++	 *   2: This element is an indefinite length string, part of an
++	 *      indefinite length string.
++	 *   3: This element is an indefinite length any, part of a
++	 *      definite length any.
++	 *   4: This element is an indefinite length any, part of an
++	 *      indefinite length any.
++	 *   5: This element is an indefinite length any and does not
++	 *      meet any of the above criteria. Note that this would include
++	 *      an indefinite length string type matching an indefinite
++	 *      length any template.
++	 *
++	 * In Cases #1 and #3, the definite length 'parent' element will
++	 * have allocated state->dest based on the parent elements definite
++	 * size. During the processing of 'child', sec_asn1d_parse_leaf will
++	 * have copied the (string, any) data directly into the offset of
++	 * dest, as appropriate, so there's no need for this class to still
++	 * store the child - it's already been processed.
++	 *
++	 * In Cases #2 and #4, dest will be set to the parent element's dest,
++	 * but dest->data will not have been allocated yet, due to the
++	 * indefinite length encoding. In this situation, it's necessary to
++	 * hold onto child (and all other children) until the EOC, at which
++	 * point, it becomes possible to compute 'state's overall length. Once
++	 * 'state' has a computed length, this can then be fed to 'parent' (via
++	 * this state), and then 'parent' can similarly compute the length of
++	 * all of its children up to the EOC, which will ultimately transit to
++	 * sec_asn1d_concat_substrings, determine the overall size needed,
++	 * allocate, and copy the contents (of all of parent's children, which
++	 * would include 'state', just as 'state' will have copied all of its
++	 * children via sec_asn1d_concat_substrings)
++	 *
++	 * The final case, Case #5, will manifest in that item->data and
++	 * item->len will be NULL/0, respectively, since this element was
++	 * indefinite-length encoded. In that case, both the tag and length will
++	 * already exist in state's subitems, via sec_asn1d_record_any_header,
++	 * and so the contents (aka 'child') should be added to that list of
++	 * items to concatenate in sec_asn1d_concat_substrings once the EOC
++	 * is encountered.
++	 *
++	 * To distinguish #2/#4 from #1/#3, it's sufficient to walk the ancestor
++	 * tree. If the current type is a string type, then the enclosing
++	 * construct will be that same type (#1/#2). If the current type is an
++	 * any type, then the enclosing construct is either an any type (#3/#4)
++	 * or some other type (#5). Since this is BER, this nesting relationship
++	 * between 'state' and 'parent' may go through several levels of
++	 * constructed encoding, so continue walking the ancestor chain until a
++	 * clear determination can be made.
++	 *
++	 * The variable preallocatedString is used to indicate Case #1/#3,
++	 * indicating an in-place copy has already occurred, and Cases #2, #4,
++	 * and #5 all have the same behaviour of adding a new substring.
++	 */
++	preallocatedString = PR_FALSE;
++	temp_state = state;
++	while (temp_state && item == temp_state->dest && temp_state->indefinite) {
++	    sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(temp_state);
++	    if (!parent || parent->underlying_kind != temp_state->underlying_kind) {
++	        /* Case #5 - Either this is a top-level construct or it is part
++	         * of some other element (e.g. a SEQUENCE), in which case, a
++	         * new item should be allocated. */
++	        break;
++	    }
++	    if (!parent->indefinite) {
++	        /* Cases #1 / #3 - A definite length ancestor exists, for which
++	         * this is a substring that has already copied into dest. */
++	        preallocatedString = PR_TRUE;
++	        break;
++	    }
++	    if (!parent->substring) {
++	        /* Cases #2 / #4 - If the parent is not a substring, but is
++	         * indefinite, then there's nothing further up that may have
++	         * preallocated dest, thus child will not have already
++		 * been copied in place, therefore it's necessary to save child
++		 * as a subitem. */
++	        break;
++	    }
++	    temp_state = parent;
++	}
++	if (item != NULL && item->data != NULL && !preallocatedString) {
+ 	    /*
+ 	     * Save the string away for later concatenation.
+ 	     */
diff --git a/debian/patches/series b/debian/patches/series
index 254ed53..9002ad0 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -29,3 +29,5 @@ CVE-2011-3389.patch
 CVE-2014-1569.patch
 CVE-2015-2730.patch
 CVE-2015-2721.patch
+CVE-2015-7182.patch
+CVE-2015-7181.patch
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 0000000..1b3d995
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,5 @@
+Tests: test-cert.sh
+Depends: libnss3-tools
+
+Tests: test-link.make
+Depends: libnss3-dev, pkg-config, g++
diff --git a/debian/tests/test-cert.sh b/debian/tests/test-cert.sh
new file mode 100644
index 0000000..14c0907
--- /dev/null
+++ b/debian/tests/test-cert.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+#
+# Check some basic CA operations
+
+set -e
+
+cleanup() {
+    [ -z "$DIR" ] || rm -rf "$DIR"
+}
+
+
+run_certutil() {
+    CMD="certutil -z $DIR/random -f $DIR/passwd -d sql:$DIR $@"
+    echo "Running: $CMD"
+    $CMD
+}
+
+DIR=`mktemp -p . -d`
+#trap cleanup EXIT ERR
+
+dd  bs=20 count=1 if=/dev/urandom of=$DIR/random 2>/dev/null
+echo "password" > $DIR/passwd
+
+# Create the database
+run_certutil -N
+# Create a self signed certificate
+run_certutil -S -k rsa -n test-ca -s CN=testca -t c -x 2>/dev/null
+# Create a certificate request
+run_certutil -R -k rsa -g 2048 -n test-cert -s "CN=testcert" -o $DIR/cert.req -a 2>/dev/null
+# Sign with ca
+run_certutil -C -m 10000 -c test-ca -i $DIR/cert.req -o $DIR/cert.cer -a
+run_certutil -A -n test-cert -i $DIR/cert.cer -t c -a
+
+echo -n "Checking if ca is present..."
+run_certutil -L -n test-ca >/dev/null
+echo "OK."
+
+echo -n "Checking if cert present..."
+run_certutil -L -n test-cert >/dev/null
+echo "OK."
+
+exit 0
diff --git a/debian/tests/test-link.cpp b/debian/tests/test-link.cpp
new file mode 100644
index 0000000..0880b4e
--- /dev/null
+++ b/debian/tests/test-link.cpp
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <nss.h>
+
+int main()
+{
+  int ret = 0;
+  SECStatus s;
+  char *t = strdup("/tmp/nss.XXXXXX");
+  char *tmpdir = mkdtemp(t);
+
+  if (tmpdir == NULL)
+    fprintf(stderr, "Failed to create temp directory: %s", strerror(errno));
+  
+  s = NSS_InitReadWrite(tmpdir);
+  if (s != SECSuccess)
+    ret = 2;
+  
+  NSS_Shutdown();
+  free(t);
+
+  return ret;
+}
diff --git a/debian/tests/test-link.make b/debian/tests/test-link.make
new file mode 100755
index 0000000..19e4e7c
--- /dev/null
+++ b/debian/tests/test-link.make
@@ -0,0 +1,10 @@
+#!/usr/bin/make -f
+
+all: a.out
+	./a.out
+	rm -f a.out
+
+a.out: debian/tests/test-link.cpp
+	g++ -Wall -Werror $<  $(shell pkg-config --cflags nss) $(shell pkg-config --libs nss)
+
+.PHONY: all

Reply to: