The new init functions can now fail so shouldn't be void
[openssl.git] / crypto / evp / names.c
index e0774da20d15031981b56a8dd052d79f616b6bfb..2a5606b04014fdf56c03755babd85076a1a6e76f 100644 (file)
@@ -1,25 +1,24 @@
-/* crypto/evp/names.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
- * 
+ *
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
+ *
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
+ * 4. If you include any Windows specific code (or a derivative thereof) from
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -49,7 +48,7 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- * 
+ *
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  */
 
 #include <stdio.h>
-#include "cryptlib.h"
-#include "evp.h"
-#include "objects.h"
-
-typedef struct aliases_st {
-       char *alias;
-       /* This must be the last field becaue I will allocate things
-        * so they go off the end of it */
-       char name[4];
-       } ALIASES;
-
-static STACK /* ALIASES */ *aliases=NULL;
-static STACK /* EVP_CIPHERS */ *ciphers=NULL;
-static STACK /* EVP_MD */ *digests=NULL;
-
-static int cipher_nid_cmp(a,b)
-EVP_CIPHER **a,**b;
-       { return((*a)->nid - (*b)->nid); }
-
-static int digest_type_cmp(a,b)
-EVP_MD **a,**b;
-       { return((*a)->pkey_type - (*b)->pkey_type); }
-
-int EVP_add_cipher(c)
-EVP_CIPHER *c;
-       {
-       int i;
-
-       if (ciphers == NULL)
-               {
-               ciphers=sk_new(cipher_nid_cmp);
-               if (ciphers == NULL) return(0);
-               }
-       if ((i=sk_find(ciphers,(char *)c)) >= 0)
-               {
-               if (sk_value(ciphers,i) == (char *)c)
-                       return(1);
-               sk_delete(ciphers,i);
-               }
-       return(sk_push(ciphers,(char *)c));
-       }
-
-int EVP_add_digest(md)
-EVP_MD *md;
-       {
-       int i;
-       char *n;
-
-       if (digests == NULL)
-               {
-               digests=sk_new(digest_type_cmp);
-               if (digests == NULL) return(0);
-               }
-       if ((i=sk_find(digests,(char *)md)) >= 0)
-               {
-               if (sk_value(digests,i) == (char *)md)
-                       return(1);
-               sk_delete(digests,i);
-               }
-       if (md->type != md->pkey_type)
-               {
-               n=OBJ_nid2sn(md->pkey_type);
-               EVP_add_alias(n,OBJ_nid2sn(md->type));
-               EVP_add_alias(n,OBJ_nid2ln(md->type));
-               }
-       sk_push(digests,(char *)md);
-       return(1);
-       }
-
-static int alias_cmp(a,b)
-ALIASES **a,**b;
-       {
-       return(strcmp((*a)->alias,(*b)->alias));
-       }
-
-int EVP_add_alias(name,aname)
-char *name;
-char *aname;
-       {
-       int l1,l2,i;
-       ALIASES *a;
-       char *p;
-
-       if ((name == NULL) || (aname == NULL)) return(0);
-       l1=strlen(name)+1;
-       l2=strlen(aname)+1;
-       i=sizeof(ALIASES)+l1+l2;
-       if ((a=(ALIASES *)Malloc(i)) == NULL)
-               return(0);
-       strcpy(a->name,name);
-       p= &(a->name[l1]);
-       strcpy(p,aname);
-       a->alias=p;
-
-       if (aliases == NULL)
-               {
-               aliases=sk_new(alias_cmp);
-               if (aliases == NULL) goto err;
-               }
-
-       if ((i=sk_find(aliases,(char *)a)) >= 0)
-               {
-               Free(sk_delete(aliases,i));
-               }
-       if (!sk_push(aliases,(char *)a)) goto err;
-       return(1);
-err:
-       return(0);
-       }
-
-int EVP_delete_alias(name)
-char *name;
-       {
-       ALIASES a;
-       int i;
-
-       if (aliases != NULL)
-               {
-               a.alias=name;
-               if ((i=sk_find(aliases,(char *)&a)) >= 0)
-                       {
-                       Free(sk_delete(aliases,i));
-                       return(1);
-                       }
-               }
-       return(0);
-       }
-
-EVP_CIPHER *EVP_get_cipherbyname(name)
-char *name;
-       {
-       int nid,num=6,i;
-       EVP_CIPHER c,*cp;
-       ALIASES a,*ap;
-
-       if (ciphers == NULL) return(NULL);
-       for (;;)
-               {
-               if (num-- <= 0) return(NULL);
-               if (aliases != NULL)
-                       {
-                       a.alias=name;
-                       i=sk_find(aliases,(char *)&a);
-                       if (i >= 0)
-                               {
-                               ap=(ALIASES *)sk_value(aliases,i);
-                               name=ap->name;
-                               continue;
-                               }
-                       }
-
-               nid=OBJ_txt2nid(name);
-               if (nid == NID_undef) return(NULL);
-               c.nid=nid;
-               i=sk_find(ciphers,(char *)&c);
-               if (i >= 0)
-                       {
-                       cp=(EVP_CIPHER *)sk_value(ciphers,i);
-                       return(cp);
-                       }
-               else
-                       return(NULL);
-               }
-       }
-
-EVP_MD *EVP_get_digestbyname(name)
-char *name;
-       {
-       int nid,num=6,i;
-       EVP_MD c,*cp;
-       ALIASES a,*ap;
-
-       if (digests == NULL) return(NULL);
-
-       for (;;)
-               {
-               if (num-- <= 0) return(NULL);
-
-               if (aliases != NULL)
-                       {
-                       a.alias=name;
-                       i=sk_find(aliases,(char *)&a);
-                       if (i >= 0)
-                               {
-                               ap=(ALIASES *)sk_value(aliases,i);
-                               name=ap->name;
-                               continue;
-                               }
-                       }
-
-               nid=OBJ_txt2nid(name);
-               if (nid == NID_undef) return(NULL);
-               c.pkey_type=nid;
-               i=sk_find(digests,(char *)&c);
-               if (i >= 0)
-                       {
-                       cp=(EVP_MD *)sk_value(digests,i);
-                       return(cp);
-                       }
-               else
-                       return(NULL);
-               }
-       }
-
-void EVP_cleanup()
-       {
-       int i;
-
-       if (aliases != NULL)
-               {
-               for (i=0; i<sk_num(aliases); i++)
-                       Free(sk_value(aliases,i));
-               sk_free(aliases);
-               aliases=NULL;
-               }
-       if (ciphers != NULL)
-               {
-               sk_free(ciphers);
-               ciphers=NULL;
-               }
-       if (digests != NULL)
-               {
-               sk_free(digests);
-               digests=NULL;
-               }
-       }
+#include "internal/cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+#include "internal/evp_int.h"
+
+int EVP_add_cipher(const EVP_CIPHER *c)
+{
+    int r;
+
+    if (c == NULL)
+        return 0;
+
+    r = OBJ_NAME_add(OBJ_nid2sn(c->nid), OBJ_NAME_TYPE_CIPHER_METH,
+                     (const char *)c);
+    if (r == 0)
+        return (0);
+    check_defer(c->nid);
+    r = OBJ_NAME_add(OBJ_nid2ln(c->nid), OBJ_NAME_TYPE_CIPHER_METH,
+                     (const char *)c);
+    return (r);
+}
+
+int EVP_add_digest(const EVP_MD *md)
+{
+    int r;
+    const char *name;
+
+    name = OBJ_nid2sn(md->type);
+    r = OBJ_NAME_add(name, OBJ_NAME_TYPE_MD_METH, (const char *)md);
+    if (r == 0)
+        return (0);
+    check_defer(md->type);
+    r = OBJ_NAME_add(OBJ_nid2ln(md->type), OBJ_NAME_TYPE_MD_METH,
+                     (const char *)md);
+    if (r == 0)
+        return (0);
+
+    if (md->pkey_type && md->type != md->pkey_type) {
+        r = OBJ_NAME_add(OBJ_nid2sn(md->pkey_type),
+                         OBJ_NAME_TYPE_MD_METH | OBJ_NAME_ALIAS, name);
+        if (r == 0)
+            return (0);
+        check_defer(md->pkey_type);
+        r = OBJ_NAME_add(OBJ_nid2ln(md->pkey_type),
+                         OBJ_NAME_TYPE_MD_METH | OBJ_NAME_ALIAS, name);
+    }
+    return (r);
+}
+
+const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
+{
+    const EVP_CIPHER *cp;
+
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL))
+        return NULL;
+
+    cp = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
+    return (cp);
+}
+
+const EVP_MD *EVP_get_digestbyname(const char *name)
+{
+    const EVP_MD *cp;
+
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL))
+        return NULL;
+
+    cp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
+    return (cp);
+}
+
+void EVP_cleanup(void)
+{
+    OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
+    OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
+    /*
+     * The above calls will only clean out the contents of the name hash
+     * table, but not the hash table itself.  The following line does that
+     * part.  -- Richard Levitte
+     */
+    OBJ_NAME_cleanup(-1);
+
+    EVP_PBE_cleanup();
+    if (obj_cleanup_defer == 2) {
+        obj_cleanup_defer = 0;
+        OBJ_cleanup();
+    }
+    OBJ_sigid_free();
+}
+
+struct doall_cipher {
+    void *arg;
+    void (*fn) (const EVP_CIPHER *ciph,
+                const char *from, const char *to, void *arg);
+};
+
+static void do_all_cipher_fn(const OBJ_NAME *nm, void *arg)
+{
+    struct doall_cipher *dc = arg;
+    if (nm->alias)
+        dc->fn(NULL, nm->name, nm->data, dc->arg);
+    else
+        dc->fn((const EVP_CIPHER *)nm->data, nm->name, NULL, dc->arg);
+}
+
+void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph,
+                                   const char *from, const char *to, void *x),
+                       void *arg)
+{
+    struct doall_cipher dc;
+
+    /* Ignore errors */
+    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL);
+
+    dc.fn = fn;
+    dc.arg = arg;
+    OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc);
+}
+
+void EVP_CIPHER_do_all_sorted(void (*fn) (const EVP_CIPHER *ciph,
+                                          const char *from, const char *to,
+                                          void *x), void *arg)
+{
+    struct doall_cipher dc;
+
+    /* Ignore errors */
+    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL);
+
+    dc.fn = fn;
+    dc.arg = arg;
+    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc);
+}
+
+struct doall_md {
+    void *arg;
+    void (*fn) (const EVP_MD *ciph,
+                const char *from, const char *to, void *arg);
+};
+
+static void do_all_md_fn(const OBJ_NAME *nm, void *arg)
+{
+    struct doall_md *dc = arg;
+    if (nm->alias)
+        dc->fn(NULL, nm->name, nm->data, dc->arg);
+    else
+        dc->fn((const EVP_MD *)nm->data, nm->name, NULL, dc->arg);
+}
+
+void EVP_MD_do_all(void (*fn) (const EVP_MD *md,
+                               const char *from, const char *to, void *x),
+                   void *arg)
+{
+    struct doall_md dc;
+
+    /* Ignore errors */
+    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+
+    dc.fn = fn;
+    dc.arg = arg;
+    OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
+}
+
+void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md,
+                                      const char *from, const char *to,
+                                      void *x), void *arg)
+{
+    struct doall_md dc;
+
+    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+
+    dc.fn = fn;
+    dc.arg = arg;
+    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
+}