| /* context.c - Context management |
| * Copyright (C) 2013 g10 Code GmbH |
| * |
| * This file is part of Libgcrypt. |
| * |
| * Libgcrypt is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU Lesser General Public License as |
| * published by the Free Software Foundation; either version 2.1 of |
| * the License, or (at your option) any later version. |
| * |
| * Libgcrypt is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this program; if not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include <config.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdarg.h> |
| #include <unistd.h> |
| |
| #include "g10lib.h" |
| #include "mpi.h" |
| #include "context.h" |
| |
| #define CTX_MAGIC "cTx" |
| #define CTX_MAGIC_LEN 3 |
| |
| |
| /* The definition of the generic context object. The public typedef |
| gcry_ctx_t is used to access it. */ |
| struct gcry_context |
| { |
| char magic[CTX_MAGIC_LEN]; /* Magic value to cross check that this |
| is really a context object. */ |
| char type; /* The type of the context (CONTEXT_TYPE_foo). */ |
| |
| void (*deinit)(void*); /* Function used to free the private part. */ |
| PROPERLY_ALIGNED_TYPE u; |
| }; |
| |
| |
| /* Allocate a fresh generic context of contect TYPE and allocate |
| LENGTH extra bytes for private use of the type handler. DEINIT is a |
| fucntion used called to deinitialize the private part; it may be |
| NULL if de-initialization is not required. Returns NULL and sets |
| ERRNO if memory allocation failed. */ |
| gcry_ctx_t |
| _gcry_ctx_alloc (int type, size_t length, void (*deinit)(void*)) |
| { |
| gcry_ctx_t ctx; |
| |
| switch (type) |
| { |
| case CONTEXT_TYPE_EC: |
| break; |
| default: |
| log_bug ("bad context type %d given to _gcry_ctx_alloc\n", type); |
| break; |
| } |
| |
| if (length < sizeof (PROPERLY_ALIGNED_TYPE)) |
| length = sizeof (PROPERLY_ALIGNED_TYPE); |
| |
| ctx = xtrycalloc (1, sizeof *ctx - sizeof (PROPERLY_ALIGNED_TYPE) + length); |
| if (!ctx) |
| return NULL; |
| memcpy (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN); |
| ctx->type = type; |
| ctx->deinit = deinit; |
| |
| return ctx; |
| } |
| |
| |
| /* Return a pointer to the private part of the context CTX. TYPE is |
| the requested context type. Using an explicit type allows to cross |
| check the type and eventually allows to store several private |
| contexts in one context object. The function does not return an |
| error but aborts if the provided CTX is not valid. */ |
| void * |
| _gcry_ctx_get_pointer (gcry_ctx_t ctx, int type) |
| { |
| if (!ctx || memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN)) |
| log_fatal ("bad pointer %p passed to _gcry_ctx_get_pointer\n", ctx); |
| if (ctx->type != type) |
| log_fatal ("wrong context type %d request for context %p of type %d\n", |
| type, ctx, ctx->type); |
| return &ctx->u; |
| } |
| |
| /* Return a pointer to the private part of the context CTX. TYPE is |
| the requested context type. Using an explicit type allows to cross |
| check the type and eventually allows to store several private |
| contexts in one context object. In contrast to |
| _gcry_ctx_get_pointer, this function returns NULL if no context for |
| the given type was found. If CTX is NULL the function does not |
| abort but returns NULL. */ |
| void * |
| _gcry_ctx_find_pointer (gcry_ctx_t ctx, int type) |
| { |
| if (!ctx) |
| return NULL; |
| if (memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN)) |
| log_fatal ("bad pointer %p passed to _gcry_ctx_get_pointer\n", ctx); |
| if (ctx->type != type) |
| return NULL; |
| return &ctx->u; |
| } |
| |
| |
| /* Release the generic context CTX. */ |
| void |
| _gcry_ctx_release (gcry_ctx_t ctx) |
| { |
| if (!ctx) |
| return; |
| if (memcmp (ctx->magic, CTX_MAGIC, CTX_MAGIC_LEN)) |
| log_fatal ("bad pointer %p passed to gcry_ctx_relase\n", ctx); |
| switch (ctx->type) |
| { |
| case CONTEXT_TYPE_EC: |
| break; |
| default: |
| log_fatal ("bad context type %d detected in gcry_ctx_relase\n", |
| ctx->type); |
| break; |
| } |
| if (ctx->deinit) |
| ctx->deinit (&ctx->u); |
| xfree (ctx); |
| } |