More secure storage of key material.
[openssl.git] / crypto / bn / bn_lib.c
index 6fc0e396bfa53352838bdca6007ccc64953c48b5..b5f827a36cf8af9daaddaaa8591b584d5c2759bb 100644 (file)
@@ -63,7 +63,7 @@
 
 #include <assert.h>
 #include <limits.h>
-#include "cryptlib.h"
+#include "internal/cryptlib.h"
 #include "bn_lcl.h"
 
 const char BN_version[] = "Big Number" OPENSSL_VERSION_PTEXT;
@@ -232,8 +232,12 @@ void BN_clear_free(BIGNUM *a)
     bn_check_top(a);
     if (a->d != NULL) {
         OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0]));
-        if (!(BN_get_flags(a, BN_FLG_STATIC_DATA)))
-            OPENSSL_free(a->d);
+        if (!(BN_get_flags(a, BN_FLG_STATIC_DATA))) {
+            if (BN_get_flags(a,BN_FLG_SECURE))
+                OPENSSL_secure_free(a->d);
+            else
+                OPENSSL_free(a->d);
+        }
     }
     i = BN_get_flags(a, BN_FLG_MALLOCED);
     OPENSSL_cleanse(a, sizeof(BIGNUM));
@@ -247,7 +251,12 @@ void BN_free(BIGNUM *a)
         return;
     bn_check_top(a);
     if (!BN_get_flags(a, BN_FLG_STATIC_DATA))
-        OPENSSL_free(a->d);
+    if ((a->d != NULL) && !(BN_get_flags(a, BN_FLG_STATIC_DATA))) {
+        if (BN_get_flags(a, BN_FLG_SECURE))
+            OPENSSL_secure_free(a->d);
+        else
+            OPENSSL_free(a->d);
+    }
     if (a->flags & BN_FLG_MALLOCED)
         OPENSSL_free(a);
     else {
@@ -260,7 +269,7 @@ void BN_free(BIGNUM *a)
 
 void BN_init(BIGNUM *a)
 {
-    memset(a, 0, sizeof(BIGNUM));
+    memset(a, 0, sizeof(*a));
     bn_check_top(a);
 }
 
@@ -281,6 +290,14 @@ BIGNUM *BN_new(void)
     return (ret);
 }
 
+ BIGNUM *BN_secure_new(void)
+ {
+     BIGNUM *ret = BN_new();
+     if (ret)
+         ret->flags |= BN_FLG_SECURE;
+     return (ret);
+ }
+
 /* This is used both by bn_expand2() and bn_dup_expand() */
 /* The caller MUST check that words > b->dmax before calling this */
 static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
@@ -299,7 +316,10 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
         BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
         return (NULL);
     }
-    a = A = OPENSSL_malloc(sizeof(*a) * words);
+    if (BN_get_flags(b,BN_FLG_SECURE))
+        a = A = OPENSSL_secure_malloc(words * sizeof(*a));
+    else
+        a = A = OPENSSL_malloc(words * sizeof(*a));
     if (A == NULL) {
         BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE);
         return (NULL);
@@ -311,7 +331,7 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
      * function - what's important is constant time operation (we're not
      * actually going to use the data)
      */
-    memset(a, 0, sizeof(BN_ULONG) * words);
+    memset(a, 0, sizeof(*a) * words);
 #endif
 
 #if 1
@@ -355,7 +375,7 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
         }
     }
 #else
-    memset(A, 0, sizeof(BN_ULONG) * words);
+    memset(A, 0, sizeof(*A) * words);
     memcpy(A, b->d, sizeof(b->d[0]) * b->top);
 #endif
 
@@ -378,7 +398,12 @@ BIGNUM *bn_expand2(BIGNUM *b, int words)
         BN_ULONG *a = bn_expand_internal(b, words);
         if (!a)
             return NULL;
-        OPENSSL_free(b->d);
+        if (b->d) {
+            if (BN_get_flags(b,BN_FLG_SECURE))
+                OPENSSL_secure_free(b->d);
+            else
+                OPENSSL_free(b->d);
+        }
         b->d = a;
         b->dmax = words;
     }
@@ -395,7 +420,7 @@ BIGNUM *BN_dup(const BIGNUM *a)
         return NULL;
     bn_check_top(a);
 
-    t = BN_new();
+    t = BN_get_flags(a, BN_FLG_SECURE) ? BN_secure_new() : BN_new();
     if (t == NULL)
         return NULL;
     if (!BN_copy(t, a)) {
@@ -492,7 +517,7 @@ void BN_clear(BIGNUM *a)
 {
     bn_check_top(a);
     if (a->d != NULL)
-        memset(a->d, 0, a->dmax * sizeof(a->d[0]));
+        memset(a->d, 0, sizeof(*a->d) * a->dmax);
     a->top = 0;
     a->neg = 0;
 }