Tizen 2.0 Release
[external/libgnutls26.git] / lib / gnutls_psk_netconf.c
1 /*
2  * Copyright (C) 2008, 2010 Free Software Foundation, Inc.
3  *
4  * Author: Simon Josefsson
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21  * USA
22  *
23  */
24
25 /* Functions to support draft-ietf-netconf-tls-01.txt. */
26
27 #include <gnutls_int.h>
28 #include <gnutls_hash_int.h>
29 #include <gnutls_errors.h>
30
31 #ifdef ENABLE_PSK
32
33
34 /**
35  * gnutls_psk_netconf_derive_key:
36  * @password: zero terminated string containing password.
37  * @psk_identity: zero terminated string with PSK identity.
38  * @psk_identity_hint: zero terminated string with PSK identity hint.
39  * @output_key: output variable, contains newly allocated *data pointer.
40  *
41  * This function will derive a PSK key from a password, for use with
42  * the Netconf protocol.
43  *
44  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
45  *
46  * Since: 2.4.0
47  *
48  * Deprecated: The need for this interface was dropped from the
49  * standard on publication as a RFC.  The function works now but will
50  * return a hard failure in a future release.
51  */
52 int
53 gnutls_psk_netconf_derive_key (const char *password,
54                                const char *psk_identity,
55                                const char *psk_identity_hint,
56                                gnutls_datum_t * output_key)
57 {
58   const char netconf_key_pad[] = "Key Pad for Netconf";
59   size_t sha1len = _gnutls_hash_get_algo_len (GNUTLS_DIG_SHA1);
60   size_t hintlen = strlen (psk_identity_hint);
61   digest_hd_st dig;
62   char *inner;
63   size_t innerlen;
64   int rc;
65
66   /*
67    * PSK = SHA-1(SHA-1(psk_identity + "Key Pad for Netconf" + password) +
68    *             psk_identity_hint)
69    *
70    */
71
72   rc = _gnutls_hash_init (&dig, GNUTLS_DIG_SHA1);
73   if (rc < 0)
74     {
75       gnutls_assert ();
76       return rc;
77     }
78
79   rc = _gnutls_hash (&dig, psk_identity, strlen (psk_identity));
80   if (rc < 0)
81     {
82       gnutls_assert ();
83       _gnutls_hash_deinit (&dig, NULL);
84       return rc;
85     }
86
87   rc = _gnutls_hash (&dig, netconf_key_pad, strlen (netconf_key_pad));
88   if (rc < 0)
89     {
90       gnutls_assert ();
91       _gnutls_hash_deinit (&dig, NULL);
92       return rc;
93     }
94
95   rc = _gnutls_hash (&dig, password, strlen (password));
96   if (rc < 0)
97     {
98       gnutls_assert ();
99       _gnutls_hash_deinit (&dig, NULL);
100       return rc;
101     }
102
103   innerlen = sha1len + hintlen;
104   inner = gnutls_malloc (innerlen);
105   _gnutls_hash_deinit (&dig, inner);
106   if (inner == NULL)
107     {
108       gnutls_assert ();
109       return GNUTLS_E_MEMORY_ERROR;
110     }
111
112   memcpy (inner + sha1len, psk_identity_hint, hintlen);
113
114   rc = _gnutls_hash_init (&dig, GNUTLS_DIG_SHA1);
115   if (rc < 0)
116     {
117       gnutls_assert ();
118       gnutls_free (inner);
119       return rc;
120     }
121
122   rc = _gnutls_hash (&dig, inner, innerlen);
123   gnutls_free (inner);
124   if (rc < 0)
125     {
126       gnutls_assert ();
127       _gnutls_hash_deinit (&dig, NULL);
128       return rc;
129     }
130
131   output_key->data = gnutls_malloc (sha1len);
132   _gnutls_hash_deinit (&dig, output_key->data);
133   if (output_key->data == NULL)
134     {
135       gnutls_assert ();
136       return GNUTLS_E_MEMORY_ERROR;
137     }
138   output_key->size = sha1len;
139
140   return 0;
141 }
142
143 #endif /* ENABLE_PSK */