MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cert_wrapper.cpp
1 /*
2  Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; see the file COPYING. If not, write to the
15  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16  MA 02110-1301 USA.
17 */
18 
19 
20 /* The certificate wrapper source implements certificate management functions
21  *
22  */
23 
24 #include "runtime.hpp"
25 #include "cert_wrapper.hpp"
26 #include "yassl_int.hpp"
27 #include "error.hpp"
28 
29 #if defined(USE_CML_LIB)
30  #include "cmapi_cpp.h"
31 #else
32  #include "asn.hpp"
33  #include "file.hpp"
34 #endif // USE_CML_LIB
35 
36 
37 namespace yaSSL {
38 
39 
40 x509::x509(uint sz) : length_(sz), buffer_(NEW_YS opaque[sz])
41 {
42 }
43 
44 
45 x509::~x509()
46 {
47  ysArrayDelete(buffer_);
48 }
49 
50 
51 x509::x509(const x509& that) : length_(that.length_),
52  buffer_(NEW_YS opaque[length_])
53 {
54  memcpy(buffer_, that.buffer_, length_);
55 }
56 
57 
58 void x509::Swap(x509& that)
59 {
60  STL::swap(length_, that.length_);
61  STL::swap(buffer_, that.buffer_);
62 }
63 
64 
65 x509& x509::operator=(const x509& that)
66 {
67  x509 temp(that);
68  Swap(temp);
69  return *this;
70 }
71 
72 
73 uint x509::get_length() const
74 {
75  return length_;
76 }
77 
78 
79 const opaque* x509::get_buffer() const
80 {
81  return buffer_;
82 }
83 
84 
85 opaque* x509::use_buffer()
86 {
87  return buffer_;
88 }
89 
90 
91 //CertManager
92 CertManager::CertManager()
93  : peerX509_(0), selfX509_(0), verifyPeer_(false), verifyNone_(false), failNoCert_(false),
94  sendVerify_(false), verifyCallback_(0)
95 {}
96 
97 
98 CertManager::~CertManager()
99 {
100  ysDelete(peerX509_);
101  ysDelete(selfX509_);
102 
103  STL::for_each(signers_.begin(), signers_.end(), del_ptr_zero()) ;
104 
105  STL::for_each(peerList_.begin(), peerList_.end(), del_ptr_zero()) ;
106 
107  STL::for_each(list_.begin(), list_.end(), del_ptr_zero()) ;
108 }
109 
110 
111 bool CertManager::verifyPeer() const
112 {
113  return verifyPeer_;
114 }
115 
116 
117 bool CertManager::verifyNone() const
118 {
119  return verifyNone_;
120 }
121 
122 
123 bool CertManager::failNoCert() const
124 {
125  return failNoCert_;
126 }
127 
128 
129 bool CertManager::sendVerify() const
130 {
131  return sendVerify_;
132 }
133 
134 
135 void CertManager::setVerifyPeer()
136 {
137  verifyPeer_ = true;
138 }
139 
140 
141 void CertManager::setVerifyNone()
142 {
143  verifyNone_ = true;
144 }
145 
146 
147 void CertManager::setFailNoCert()
148 {
149  failNoCert_ = true;
150 }
151 
152 
153 void CertManager::setSendVerify()
154 {
155  sendVerify_ = true;
156 }
157 
158 
159 void CertManager::setVerifyCallback(VerifyCallback vc)
160 {
161  verifyCallback_ = vc;
162 }
163 
164 
165 void CertManager::AddPeerCert(x509* x)
166 {
167  peerList_.push_back(x); // take ownership
168 }
169 
170 
171 void CertManager::CopySelfCert(const x509* x)
172 {
173  if (x)
174  list_.push_back(NEW_YS x509(*x));
175 }
176 
177 
178 // add to signers
179 int CertManager::CopyCaCert(const x509* x)
180 {
181  TaoCrypt::Source source(x->get_buffer(), x->get_length());
182  TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_,
183  TaoCrypt::CertDecoder::CA);
184 
185  if (!cert.GetError().What()) {
186  const TaoCrypt::PublicKey& key = cert.GetPublicKey();
187  signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(),
188  cert.GetCommonName(), cert.GetHash()));
189  }
190  // just don't add, not an error return cert.GetError().What();
191  return 0;
192 }
193 
194 
195 const x509* CertManager::get_cert() const
196 {
197  return list_.front();
198 }
199 
200 
201 const opaque* CertManager::get_peerKey() const
202 {
203  return peerPublicKey_.get_buffer();
204 }
205 
206 
207 X509* CertManager::get_peerX509() const
208 {
209  return peerX509_;
210 }
211 
212 
213 X509* CertManager::get_selfX509() const
214 {
215  return selfX509_;
216 }
217 
218 
219 SignatureAlgorithm CertManager::get_peerKeyType() const
220 {
221  return peerKeyType_;
222 }
223 
224 
225 SignatureAlgorithm CertManager::get_keyType() const
226 {
227  return keyType_;
228 }
229 
230 
231 uint CertManager::get_peerKeyLength() const
232 {
233  return peerPublicKey_.get_size();
234 }
235 
236 
237 const opaque* CertManager::get_privateKey() const
238 {
239  return privateKey_.get_buffer();
240 }
241 
242 
243 uint CertManager::get_privateKeyLength() const
244 {
245  return privateKey_.get_size();
246 }
247 
248 
249 // Validate the peer's certificate list, from root to peer (last to first)
250 int CertManager::Validate()
251 {
252  CertList::reverse_iterator last = peerList_.rbegin();
253  size_t count = peerList_.size();
254 
255  while ( count > 1 ) {
256  TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
257  TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_);
258 
259  if (int err = cert.GetError().What())
260  return err;
261 
262  const TaoCrypt::PublicKey& key = cert.GetPublicKey();
263  signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(),
264  cert.GetCommonName(), cert.GetHash()));
265  ++last;
266  --count;
267  }
268 
269  if (count) {
270  // peer's is at the front
271  TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length());
272  TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_);
273 
274  int err = cert.GetError().What();
275  if ( err && err != TaoCrypt::SIG_OTHER_E)
276  return err;
277 
278  uint sz = cert.GetPublicKey().size();
279  peerPublicKey_.allocate(sz);
280  peerPublicKey_.assign(cert.GetPublicKey().GetKey(), sz);
281 
282  if (cert.GetKeyType() == TaoCrypt::RSAk)
283  peerKeyType_ = rsa_sa_algo;
284  else
285  peerKeyType_ = dsa_sa_algo;
286 
287  size_t iSz = strlen(cert.GetIssuer()) + 1;
288  size_t sSz = strlen(cert.GetCommonName()) + 1;
289  ASN1_STRING beforeDate, afterDate;
290  beforeDate.data= (unsigned char *) cert.GetBeforeDate();
291  beforeDate.type= cert.GetBeforeDateType();
292  beforeDate.length= strlen((char *) beforeDate.data) + 1;
293  afterDate.data= (unsigned char *) cert.GetAfterDate();
294  afterDate.type= cert.GetAfterDateType();
295  afterDate.length= strlen((char *) afterDate.data) + 1;
296  peerX509_ = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(),
297  sSz, &beforeDate, &afterDate);
298 
299  if (err == TaoCrypt::SIG_OTHER_E && verifyCallback_) {
300  X509_STORE_CTX store;
301  store.error = err;
302  store.error_depth = static_cast<int>(count) - 1;
303  store.current_cert = peerX509_;
304 
305  int ok = verifyCallback_(0, &store);
306  if (ok) return 0;
307  }
308 
309  if (err == TaoCrypt::SIG_OTHER_E) return err;
310  }
311  return 0;
312 }
313 
314 
315 // Set the private key
316 int CertManager::SetPrivateKey(const x509& key)
317 {
318  privateKey_.allocate(key.get_length());
319  privateKey_.assign(key.get_buffer(), key.get_length());
320 
321  // set key type
322  if (x509* cert = list_.front()) {
323  TaoCrypt::Source source(cert->get_buffer(), cert->get_length());
324  TaoCrypt::CertDecoder cd(source, false);
325  cd.DecodeToKey();
326  if (int err = cd.GetError().What())
327  return err;
328  if (cd.GetKeyType() == TaoCrypt::RSAk)
329  keyType_ = rsa_sa_algo;
330  else
331  keyType_ = dsa_sa_algo;
332 
333  size_t iSz = strlen(cd.GetIssuer()) + 1;
334  size_t sSz = strlen(cd.GetCommonName()) + 1;
335  ASN1_STRING beforeDate, afterDate;
336  beforeDate.data= (unsigned char *) cd.GetBeforeDate();
337  beforeDate.type= cd.GetBeforeDateType();
338  beforeDate.length= strlen((char *) beforeDate.data) + 1;
339  afterDate.data= (unsigned char *) cd.GetAfterDate();
340  afterDate.type= cd.GetAfterDateType();
341  afterDate.length= strlen((char *) afterDate.data) + 1;
342  selfX509_ = NEW_YS X509(cd.GetIssuer(), iSz, cd.GetCommonName(),
343  sSz, &beforeDate, &afterDate);
344  }
345  return 0;
346 }
347 
348 
349 // Store OpenSSL type peer's cert
350 void CertManager::setPeerX509(X509* x)
351 {
352  if (x == 0) return;
353 
354  X509_NAME* issuer = x->GetIssuer();
355  X509_NAME* subject = x->GetSubject();
356  ASN1_STRING* before = x->GetBefore();
357  ASN1_STRING* after = x->GetAfter();
358 
359  peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(),
360  subject->GetName(), subject->GetLength(), before, after);
361 }
362 
363 
364 #if defined(USE_CML_LIB)
365 
366 // Get the peer's certificate, extract and save public key
367 void CertManager::SetPeerKey()
368 {
369  // first cert is the peer's
370  x509* main = peerList_.front();
371 
372  Bytes_struct cert;
373  cert.num = main->get_length();
374  cert.data = main->set_buffer();
375 
376  CML::Certificate cm(cert);
377  const CML::ASN::Cert& raw = cm.base();
378  CTIL::CSM_Buffer key = raw.pubKeyInfo.key;
379 
380  uint sz;
381  opaque* key_buffer = reinterpret_cast<opaque*>(key.Get(sz));
382  peerPublicKey_.allocate(sz);
383  peerPublicKey_.assign(key_buffer, sz);
384 }
385 
386 
387 #endif // USE_CML_LIB
388 
389 
390 
391 } // namespace