rndhw: add missing "memory" clobbers
[libgcrypt.git] / src / context.c
1 /* context.c - Context management
2  * Copyright (C) 2013  g10 Code GmbH
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include <unistd.h>
26
27 #include "g10lib.h"
28 #include "mpi.h"
29 #include "context.h"
30
31 #define CTX_MAGIC "cTx"
32 #define CTX_MAGIC_LEN 3
33
34
35 /* The definition of the generic context object.  The public typedef
36    gcry_ctx_t is used to access it.  */
37 struct gcry_context
38 {
39   char magic[CTX_MAGIC_LEN]; /* Magic value to cross check that this
40                                 is really a context object. */
41   char type;     /* The type of the context (CONTEXT_TYPE_foo).  */
42
43   void (*deinit)(void*); /* Function used to free the private part. */
44   PROPERLY_ALIGNED_TYPE u;
45 };
46
47
48 /* Allocate a fresh generic context of contect TYPE and allocate
49    LENGTH extra bytes for private use of the type handler. DEINIT is a
50    function used called to deinitialize the private part; it may be
51    NULL if de-initialization is not required.  Returns NULL and sets
52    ERRNO if memory allocation failed.  */
53 gcry_ctx_t
54 _gcry_ctx_alloc (int type, size_t length, void (*deinit)(void*))
55 {
56   gcry_ctx_t ctx;
57
58   switch (type)
59     {
60     case CONTEXT_TYPE_EC:
61       break;
62     default:
63       log_bug ("bad context type %d given to _gcry_ctx_alloc\n", type);
64       break;
65     }
66
67   if (length < sizeof (PROPERLY_ALIGNED_TYPE))
68     length = sizeof (PROPERLY_ALIGNED_TYPE);
69
70   ctx = xtrycalloc (1, sizeof *ctx - sizeof (PROPERLY_ALIGNED_TYPE) + length);
71   if (!ctx)
72     return NULL;
73   memcpy (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN);
74   ctx->type = type;
75   ctx->deinit = deinit;
76
77   return ctx;
78 }
79
80
81 /* Return a pointer to the private part of the context CTX.  TYPE is
82    the requested context type.  Using an explicit type allows to cross
83    check the type and eventually allows to store several private
84    contexts in one context object.  The function does not return an
85    error but aborts if the provided CTX is not valid.  */
86 void *
87 _gcry_ctx_get_pointer (gcry_ctx_t ctx, int type)
88 {
89   if (!ctx || memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN))
90     log_fatal ("bad pointer %p passed to _gcry_ctx_get_pointer\n", ctx);
91   if (ctx->type != type)
92     log_fatal ("wrong context type %d request for context %p of type %d\n",
93                type, ctx, ctx->type);
94   return &ctx->u;
95 }
96
97 /* Return a pointer to the private part of the context CTX.  TYPE is
98    the requested context type.  Using an explicit type allows to cross
99    check the type and eventually allows to store several private
100    contexts in one context object.  In contrast to
101    _gcry_ctx_get_pointer, this function returns NULL if no context for
102    the given type was found.  If CTX is NULL the function does not
103    abort but returns NULL.  */
104 void *
105 _gcry_ctx_find_pointer (gcry_ctx_t ctx, int type)
106 {
107   if (!ctx)
108     return NULL;
109   if (memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN))
110     log_fatal ("bad pointer %p passed to _gcry_ctx_get_pointer\n", ctx);
111   if (ctx->type != type)
112     return NULL;
113   return &ctx->u;
114 }
115
116
117 /* Release the generic context CTX.  */
118 void
119 _gcry_ctx_release (gcry_ctx_t ctx)
120 {
121   if (!ctx)
122     return;
123   if (memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN))
124     log_fatal ("bad pointer %p passed to gcry_ctx_relase\n", ctx);
125   switch (ctx->type)
126     {
127     case CONTEXT_TYPE_EC:
128       break;
129     default:
130       log_fatal ("bad context type %d detected in gcry_ctx_relase\n",
131                  ctx->type);
132       break;
133     }
134   if (ctx->deinit)
135     ctx->deinit (&ctx->u);
136   xfree (ctx);
137 }