~ubuntu-branches/ubuntu/trusty/libotr2/trusty

« back to all changes in this revision

Viewing changes to src/mem.c

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2012-11-05 01:06:26 UTC
  • Revision ID: package-import@ubuntu.com-20121105010626-4m3hldpaz3jfr3wb
Tags: upstream-3.2.1
ImportĀ upstreamĀ versionĀ 3.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Off-the-Record Messaging library
 
3
 *  Copyright (C) 2004-2008  Ian Goldberg, Chris Alexander, Nikita Borisov
 
4
 *                           <otr@cypherpunks.ca>
 
5
 *
 
6
 *  This library is free software; you can redistribute it and/or
 
7
 *  modify it under the terms of version 2.1 of the GNU Lesser General
 
8
 *  Public License as published by the Free Software Foundation.
 
9
 *
 
10
 *  This library is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 *  Lesser General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU Lesser General Public
 
16
 *  License along with this library; if not, write to the Free Software
 
17
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 */
 
19
 
 
20
/* Memory allocation routines for libgcrypt.  All of the session key
 
21
 * information gets allocated through here, so we can wipe it out when
 
22
 * it's free()d.  We don't use the built-in secmem functions of
 
23
 * libgcrypt because you need to declare a fixed amount of it when you
 
24
 * start up.
 
25
 *
 
26
 * Because "secure" and "insecure" allocations from libgcrypt will get
 
27
 * handled the same way (since we're not going to be running as root,
 
28
 * and so won't actually have pinned memory), pretend all allocated
 
29
 * memory (but just from libgcrypt) is requested secure, and wipe it on
 
30
 * free(). */
 
31
 
 
32
/* Uncomment the following to add a check that our free() and realloc() only
 
33
 * get called on things returned from our malloc(). */
 
34
/* #define OTRL_MEM_MAGIC 0x31415926 */
 
35
 
 
36
/* system headers */
 
37
#ifdef OTRL_MEM_MAGIC
 
38
#include <stdio.h>
 
39
#endif
 
40
#include <stdlib.h>
 
41
 
 
42
/* libgcrypt headers */
 
43
#include <gcrypt.h>
 
44
 
 
45
/* libotr headers */
 
46
#include "mem.h"
 
47
 
 
48
static int header_size;
 
49
 
 
50
static void *otrl_mem_malloc(size_t n)
 
51
{
 
52
    void *p;
 
53
    size_t new_n = n;
 
54
    new_n += header_size;
 
55
 
 
56
    /* Check for overflow attack */
 
57
    if (new_n < n) return NULL;
 
58
    p = malloc(new_n);
 
59
    if (p == NULL) return NULL;
 
60
 
 
61
    ((size_t *)p)[0] = new_n;  /* Includes header size */
 
62
#ifdef OTRL_MEM_MAGIC
 
63
    ((size_t *)p)[1] = OTRL_MEM_MAGIC;
 
64
#endif
 
65
 
 
66
    return (void *)((char *)p + header_size);
 
67
}
 
68
 
 
69
static int otrl_mem_is_secure(const void *p)
 
70
{
 
71
    return 1;
 
72
}
 
73
 
 
74
static void otrl_mem_free(void *p)
 
75
{
 
76
    void *real_p = (void *)((char *)p - header_size);
 
77
    size_t n = ((size_t *)real_p)[0];
 
78
#ifdef OTRL_MEM_MAGIC
 
79
    if (((size_t *)real_p)[1] != OTRL_MEM_MAGIC) {
 
80
        fprintf(stderr, "Illegal free!\n");
 
81
        return;
 
82
    }
 
83
#endif
 
84
 
 
85
    /* Wipe the memory (in the same way the built-in deallocator in
 
86
     * libgcrypt would) */
 
87
    memset(real_p, 0xff, n);
 
88
    memset(real_p, 0xaa, n);
 
89
    memset(real_p, 0x55, n);
 
90
    memset(real_p, 0x00, n);
 
91
 
 
92
    free(real_p);
 
93
}
 
94
 
 
95
static void *otrl_mem_realloc(void *p, size_t n)
 
96
{
 
97
    if (p == NULL) {
 
98
        return otrl_mem_malloc(n);
 
99
    } else if (n == 0) {
 
100
        otrl_mem_free(p);
 
101
        return NULL;
 
102
    } else {
 
103
        void *real_p = (void *)((char *)p - header_size);
 
104
        void *new_p;
 
105
        size_t old_n = ((size_t *)real_p)[0];
 
106
#ifdef OTRL_MEM_MAGIC
 
107
        size_t magic = ((size_t *)real_p)[1];
 
108
#endif
 
109
        size_t new_n = n;
 
110
        new_n += header_size;
 
111
 
 
112
        /* Check for overflow attack */
 
113
        if (new_n < n) return NULL;
 
114
 
 
115
#ifdef OTRL_MEM_MAGIC
 
116
        if (magic != OTRL_MEM_MAGIC) {
 
117
            fprintf(stderr, "Illegal realloc!\n");
 
118
            return NULL;
 
119
        }
 
120
#endif
 
121
 
 
122
        if (new_n < old_n) {
 
123
            /* Overwrite the space we're about to stop using */
 
124
            void *p = (void *)((char *)real_p + new_n);
 
125
            size_t excess = old_n - new_n;
 
126
            memset(p, 0xff, excess);
 
127
            memset(p, 0xaa, excess);
 
128
            memset(p, 0x55, excess);
 
129
            memset(p, 0x00, excess);
 
130
 
 
131
            /* We don't actually need to realloc() */
 
132
            new_p = real_p;
 
133
        } else {
 
134
            new_p = realloc(real_p, new_n);
 
135
            if (new_p == NULL) return NULL;
 
136
        }
 
137
 
 
138
        ((size_t *)new_p)[0] = new_n;  /* Includes header size */
 
139
        return (void *)((char *)new_p + header_size);
 
140
    }
 
141
}
 
142
 
 
143
void otrl_mem_init(void)
 
144
{
 
145
    header_size = 8;
 
146
#ifdef OTRL_MEM_MAGIC
 
147
    if (header_size < 2*sizeof(size_t)) {
 
148
        header_size = 2*sizeof(size_t);
 
149
    }
 
150
#else
 
151
    if (header_size < sizeof(size_t)) {
 
152
        header_size = sizeof(size_t);
 
153
    }
 
154
#endif
 
155
 
 
156
    gcry_set_allocation_handler(
 
157
            otrl_mem_malloc,
 
158
            otrl_mem_malloc,
 
159
            otrl_mem_is_secure,
 
160
            otrl_mem_realloc,
 
161
            otrl_mem_free
 
162
        );
 
163
}